imagehlp: Use the IMAGE_FIRST_SECTION helper macro.
[wine.git] / dlls / mshtml / range.c
blob738818d93fb7a91753811be5ce10af84be51ba1a
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 nsIDOMRange *nsrange;
41 HTMLDocumentNode *doc;
43 struct list entry;
44 } HTMLTxtRange;
46 typedef struct {
47 DispatchEx dispex;
48 IHTMLDOMRange IHTMLDOMRange_iface;
50 nsIDOMRange *nsrange;
51 } HTMLDOMRange;
53 typedef struct {
54 WCHAR *buf;
55 DWORD len;
56 DWORD size;
57 } wstrbuf_t;
59 typedef struct {
60 UINT16 type;
61 nsIDOMNode *node;
62 UINT32 off;
63 } rangepoint_t;
65 typedef enum {
66 RU_UNKNOWN,
67 RU_CHAR,
68 RU_WORD,
69 RU_SENTENCE,
70 RU_TEXTEDIT
71 } range_unit_t;
73 static HTMLTxtRange *get_range_object(HTMLDocumentNode *doc, IHTMLTxtRange *iface)
75 HTMLTxtRange *iter;
77 LIST_FOR_EACH_ENTRY(iter, &doc->range_list, HTMLTxtRange, entry) {
78 if(&iter->IHTMLTxtRange_iface == iface)
79 return iter;
82 ERR("Could not find range in document\n");
83 return NULL;
86 static range_unit_t string_to_unit(LPCWSTR str)
88 if(!wcsicmp(str, L"character")) return RU_CHAR;
89 if(!wcsicmp(str, L"word")) return RU_WORD;
90 if(!wcsicmp(str, L"sentence")) return RU_SENTENCE;
91 if(!wcsicmp(str, L"textedit")) return RU_TEXTEDIT;
93 return RU_UNKNOWN;
96 static int string_to_nscmptype(LPCWSTR str)
98 if(!wcsicmp(str, L"StartToEnd")) return NS_START_TO_END;
99 if(!wcsicmp(str, L"StartToStart")) return NS_START_TO_START;
100 if(!wcsicmp(str, L"EndToStart")) return NS_END_TO_START;
101 if(!wcsicmp(str, L"EndToEnd")) return NS_END_TO_END;
103 return -1;
106 static UINT16 get_node_type(nsIDOMNode *node)
108 UINT16 type = 0;
110 if(node)
111 nsIDOMNode_GetNodeType(node, &type);
113 return type;
116 static void get_text_node_data(nsIDOMNode *node, nsAString *nsstr, const PRUnichar **str)
118 nsIDOMText *nstext;
119 nsresult nsres;
121 nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
122 assert(nsres == NS_OK);
124 nsAString_Init(nsstr, NULL);
125 nsres = nsIDOMText_GetData(nstext, nsstr);
126 nsIDOMText_Release(nstext);
127 if(NS_FAILED(nsres))
128 ERR("GetData failed: %08lx\n", nsres);
130 nsAString_GetData(nsstr, str);
133 static nsIDOMNode *get_child_node(nsIDOMNode *node, UINT32 off)
135 nsIDOMNodeList *node_list;
136 nsIDOMNode *ret = NULL;
138 nsIDOMNode_GetChildNodes(node, &node_list);
139 nsIDOMNodeList_Item(node_list, off, &ret);
140 nsIDOMNodeList_Release(node_list);
142 return ret;
145 /* This is very inefficient, but there is no faster way to compute index in
146 * child node list using public API. Gecko has internal nsINode::IndexOf
147 * function that we could consider exporting and use instead. */
148 static int get_child_index(nsIDOMNode *parent, nsIDOMNode *child)
150 nsIDOMNodeList *node_list;
151 nsIDOMNode *node;
152 int ret = 0;
153 nsresult nsres;
155 nsres = nsIDOMNode_GetChildNodes(parent, &node_list);
156 assert(nsres == NS_OK);
158 while(1) {
159 nsres = nsIDOMNodeList_Item(node_list, ret, &node);
160 assert(nsres == NS_OK && node);
161 if(node == child) {
162 nsIDOMNode_Release(node);
163 break;
165 nsIDOMNode_Release(node);
166 ret++;
169 nsIDOMNodeList_Release(node_list);
170 return ret;
173 static void init_rangepoint_no_addref(rangepoint_t *rangepoint, nsIDOMNode *node, UINT32 off)
175 rangepoint->type = get_node_type(node);
176 rangepoint->node = node;
177 rangepoint->off = off;
180 static void init_rangepoint(rangepoint_t *rangepoint, nsIDOMNode *node, UINT32 off)
182 nsIDOMNode_AddRef(node);
183 init_rangepoint_no_addref(rangepoint, node, 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_no_addref(iter, node, 0);
207 return TRUE;
210 /* There are no more children in the node. Move to parent. */
211 nsres = nsIDOMNode_GetParentNode(iter->node, &node);
212 assert(nsres == NS_OK);
213 if(!node)
214 return FALSE;
216 off = get_child_index(node, iter->node)+1;
217 free_rangepoint(iter);
218 init_rangepoint_no_addref(iter, node, off);
219 return TRUE;
222 static UINT32 get_child_count(nsIDOMNode *node)
224 nsIDOMNodeList *node_list;
225 UINT32 ret;
226 nsresult nsres;
228 nsres = nsIDOMNode_GetChildNodes(node, &node_list);
229 assert(nsres == NS_OK);
231 nsres = nsIDOMNodeList_GetLength(node_list, &ret);
232 nsIDOMNodeList_Release(node_list);
233 assert(nsres == NS_OK);
235 return ret;
238 static UINT32 get_text_length(nsIDOMNode *node)
240 nsIDOMText *nstext;
241 UINT32 ret;
242 nsresult nsres;
244 nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
245 assert(nsres == NS_OK);
247 nsres = nsIDOMText_GetLength(nstext, &ret);
248 nsIDOMText_Release(nstext);
249 assert(nsres == NS_OK);
251 return ret;
254 static BOOL rangepoint_prev_node(rangepoint_t *iter)
256 nsIDOMNode *node;
257 UINT32 off;
258 nsresult nsres;
260 /* Try to move to the child node. */
261 if(iter->off) {
262 node = get_child_node(iter->node, iter->off-1);
263 assert(node != NULL);
265 off = get_node_type(node) == TEXT_NODE ? get_text_length(node) : get_child_count(node);
266 free_rangepoint(iter);
267 init_rangepoint_no_addref(iter, node, off);
268 return TRUE;
271 /* There are no more children in the node. Move to parent. */
272 nsres = nsIDOMNode_GetParentNode(iter->node, &node);
273 assert(nsres == NS_OK);
274 if(!node)
275 return FALSE;
277 off = get_child_index(node, iter->node);
278 free_rangepoint(iter);
279 init_rangepoint_no_addref(iter, node, off);
280 return TRUE;
283 static void get_start_point(HTMLTxtRange *This, rangepoint_t *ret)
285 nsIDOMNode *node;
286 LONG off;
288 nsIDOMRange_GetStartContainer(This->nsrange, &node);
289 nsIDOMRange_GetStartOffset(This->nsrange, &off);
291 init_rangepoint_no_addref(ret, node, off);
294 static void get_end_point(HTMLTxtRange *This, rangepoint_t *ret)
296 nsIDOMNode *node;
297 LONG off;
299 nsIDOMRange_GetEndContainer(This->nsrange, &node);
300 nsIDOMRange_GetEndOffset(This->nsrange, &off);
302 init_rangepoint_no_addref(ret, node, off);
305 static void set_start_point(HTMLTxtRange *This, const rangepoint_t *start)
307 nsresult nsres = nsIDOMRange_SetStart(This->nsrange, start->node, start->off);
308 if(NS_FAILED(nsres))
309 ERR("failed: %08lx\n", nsres);
312 static void set_end_point(HTMLTxtRange *This, const rangepoint_t *end)
314 nsresult nsres = nsIDOMRange_SetEnd(This->nsrange, end->node, end->off);
315 if(NS_FAILED(nsres))
316 ERR("failed: %08lx\n", nsres);
319 static BOOL is_elem_tag(nsIDOMNode *node, LPCWSTR istag)
321 nsIDOMElement *elem;
322 nsAString tag_str;
323 const PRUnichar *tag;
324 BOOL ret = FALSE;
325 nsresult nsres;
327 nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMElement, (void**)&elem);
328 if(NS_FAILED(nsres))
329 return FALSE;
331 nsAString_Init(&tag_str, NULL);
332 nsIDOMElement_GetTagName(elem, &tag_str);
333 nsIDOMElement_Release(elem);
334 nsAString_GetData(&tag_str, &tag);
336 ret = !wcsicmp(tag, istag);
338 nsAString_Finish(&tag_str);
340 return ret;
343 static inline BOOL wstrbuf_init(wstrbuf_t *buf)
345 buf->len = 0;
346 buf->size = 16;
347 buf->buf = malloc(buf->size * sizeof(WCHAR));
348 if (!buf->buf) return FALSE;
349 *buf->buf = 0;
350 return TRUE;
353 static inline void wstrbuf_finish(wstrbuf_t *buf)
355 free(buf->buf);
358 static void wstrbuf_append_len(wstrbuf_t *buf, LPCWSTR str, int len)
360 if(buf->len+len >= buf->size) {
361 buf->size = 2*buf->size+len;
362 buf->buf = realloc(buf->buf, buf->size * sizeof(WCHAR));
365 memcpy(buf->buf+buf->len, str, len*sizeof(WCHAR));
366 buf->len += len;
367 buf->buf[buf->len] = 0;
370 static void wstrbuf_append_nodetxt(wstrbuf_t *buf, LPCWSTR str, int len)
372 const WCHAR *s = str;
373 WCHAR *d;
375 TRACE("%s\n", debugstr_wn(str, len));
377 if(buf->len+len >= buf->size) {
378 buf->size = 2*buf->size+len;
379 buf->buf = realloc(buf->buf, buf->size * sizeof(WCHAR));
382 if(buf->len && iswspace(buf->buf[buf->len-1])) {
383 while(s < str+len && iswspace(*s))
384 s++;
387 d = buf->buf+buf->len;
388 while(s < str+len) {
389 if(iswspace(*s)) {
390 *d++ = ' ';
391 s++;
392 while(s < str+len && iswspace(*s))
393 s++;
394 }else {
395 *d++ = *s++;
399 buf->len = d - buf->buf;
400 *d = 0;
403 static void wstrbuf_append_node(wstrbuf_t *buf, nsIDOMNode *node, BOOL ignore_text)
406 switch(get_node_type(node)) {
407 case TEXT_NODE: {
408 nsIDOMText *nstext;
409 nsAString data_str;
410 const PRUnichar *data;
412 if(ignore_text)
413 break;
415 nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
417 nsAString_Init(&data_str, NULL);
418 nsIDOMText_GetData(nstext, &data_str);
419 nsAString_GetData(&data_str, &data);
420 wstrbuf_append_nodetxt(buf, data, lstrlenW(data));
421 nsAString_Finish(&data_str);
423 nsIDOMText_Release(nstext);
425 break;
427 case ELEMENT_NODE:
428 if(is_elem_tag(node, L"br")) {
429 static const WCHAR endlW[] = {'\r','\n'};
430 wstrbuf_append_len(buf, endlW, 2);
431 }else if(is_elem_tag(node, L"hr")) {
432 static const WCHAR endl2W[] = {'\r','\n','\r','\n'};
433 wstrbuf_append_len(buf, endl2W, 4);
438 static void wstrbuf_append_node_rec(wstrbuf_t *buf, nsIDOMNode *node)
440 nsIDOMNode *iter, *tmp;
442 wstrbuf_append_node(buf, node, FALSE);
444 nsIDOMNode_GetFirstChild(node, &iter);
445 while(iter) {
446 wstrbuf_append_node_rec(buf, iter);
447 nsIDOMNode_GetNextSibling(iter, &tmp);
448 nsIDOMNode_Release(iter);
449 iter = tmp;
453 static void range_to_string(HTMLTxtRange *This, wstrbuf_t *buf)
455 rangepoint_t end_pos, iter;
456 cpp_bool collapsed;
458 nsIDOMRange_GetCollapsed(This->nsrange, &collapsed);
459 if(collapsed) {
460 wstrbuf_finish(buf);
461 buf->buf = NULL;
462 buf->size = 0;
463 return;
466 get_end_point(This, &end_pos);
467 get_start_point(This, &iter);
469 do {
470 if(iter.type == TEXT_NODE) {
471 const PRUnichar *str;
472 nsAString nsstr;
474 get_text_node_data(iter.node, &nsstr, &str);
476 if(iter.node == end_pos.node) {
477 wstrbuf_append_nodetxt(buf, str+iter.off, end_pos.off-iter.off);
478 nsAString_Finish(&nsstr);
479 break;
482 wstrbuf_append_nodetxt(buf, str+iter.off, lstrlenW(str+iter.off));
483 nsAString_Finish(&nsstr);
484 }else {
485 nsIDOMNode *node;
487 node = get_child_node(iter.node, iter.off);
488 if(node) {
489 wstrbuf_append_node(buf, node, TRUE);
490 nsIDOMNode_Release(node);
494 if(!rangepoint_next_node(&iter)) {
495 ERR("End of document?\n");
496 break;
498 }while(!rangepoint_cmp(&iter, &end_pos));
500 free_rangepoint(&iter);
501 free_rangepoint(&end_pos);
503 if(buf->len) {
504 WCHAR *p;
506 for(p = buf->buf+buf->len-1; p >= buf->buf && iswspace(*p); p--);
508 p = wcschr(p, '\r');
509 if(p)
510 *p = 0;
514 HRESULT get_node_text(HTMLDOMNode *node, BSTR *ret)
516 wstrbuf_t buf;
517 HRESULT hres = S_OK;
519 if (!wstrbuf_init(&buf))
520 return E_OUTOFMEMORY;
521 wstrbuf_append_node_rec(&buf, node->nsnode);
522 if(buf.buf && *buf.buf) {
523 *ret = SysAllocString(buf.buf);
524 if(!*ret)
525 hres = E_OUTOFMEMORY;
526 } else {
527 *ret = NULL;
529 wstrbuf_finish(&buf);
531 if(SUCCEEDED(hres))
532 TRACE("ret %s\n", debugstr_w(*ret));
533 return hres;
536 static WCHAR move_next_char(rangepoint_t *iter)
538 rangepoint_t last_space;
539 nsIDOMNode *node;
540 WCHAR cspace = 0;
541 const WCHAR *p;
543 do {
544 switch(iter->type) {
545 case TEXT_NODE: {
546 const PRUnichar *str;
547 nsAString nsstr;
548 WCHAR c;
550 get_text_node_data(iter->node, &nsstr, &str);
551 p = str+iter->off;
552 if(!*p) {
553 nsAString_Finish(&nsstr);
554 break;
557 c = *p;
558 if(iswspace(c)) {
559 while(iswspace(*p))
560 p++;
562 if(cspace)
563 free_rangepoint(&last_space);
564 else
565 cspace = ' ';
567 iter->off = p-str;
568 c = *p;
569 nsAString_Finish(&nsstr);
570 if(!c) { /* continue to skip spaces */
571 init_rangepoint(&last_space, iter->node, iter->off);
572 break;
575 return cspace;
576 }else {
577 nsAString_Finish(&nsstr);
580 /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
581 if(cspace) {
582 free_rangepoint(iter);
583 *iter = last_space;
584 return cspace;
587 iter->off++;
588 return c;
590 case ELEMENT_NODE:
591 node = get_child_node(iter->node, iter->off);
592 if(!node)
593 break;
595 if(is_elem_tag(node, L"br")) {
596 if(cspace) {
597 nsIDOMNode_Release(node);
598 free_rangepoint(iter);
599 *iter = last_space;
600 return cspace;
603 cspace = '\n';
604 init_rangepoint(&last_space, iter->node, iter->off+1);
605 }else if(is_elem_tag(node, L"hr")) {
606 nsIDOMNode_Release(node);
607 if(cspace) {
608 free_rangepoint(iter);
609 *iter = last_space;
610 return cspace;
613 iter->off++;
614 return '\n';
617 nsIDOMNode_Release(node);
619 }while(rangepoint_next_node(iter));
621 if(cspace)
622 free_rangepoint(&last_space);
624 return cspace;
627 static WCHAR move_prev_char(rangepoint_t *iter)
629 rangepoint_t last_space;
630 nsIDOMNode *node;
631 WCHAR cspace = 0;
632 const WCHAR *p;
634 do {
635 switch(iter->type) {
636 case TEXT_NODE: {
637 const PRUnichar *str;
638 nsAString nsstr;
639 WCHAR c;
641 if(!iter->off)
642 break;
644 get_text_node_data(iter->node, &nsstr, &str);
646 p = str+iter->off-1;
647 c = *p;
649 if(iswspace(c)) {
650 while(p > str && iswspace(*(p-1)))
651 p--;
653 if(cspace)
654 free_rangepoint(&last_space);
655 else
656 cspace = ' ';
658 iter->off = p-str;
659 nsAString_Finish(&nsstr);
660 if(p == str) { /* continue to skip spaces */
661 init_rangepoint(&last_space, iter->node, iter->off);
662 break;
665 return cspace;
666 }else {
667 nsAString_Finish(&nsstr);
670 /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
671 if(cspace) {
672 free_rangepoint(iter);
673 *iter = last_space;
674 return cspace;
677 iter->off--;
678 return c;
680 case ELEMENT_NODE:
681 if(!iter->off)
682 break;
684 node = get_child_node(iter->node, iter->off-1);
685 if(!node)
686 break;
688 if(is_elem_tag(node, L"br")) {
689 if(cspace)
690 free_rangepoint(&last_space);
691 cspace = '\n';
692 init_rangepoint(&last_space, iter->node, iter->off-1);
693 }else if(is_elem_tag(node, L"hr")) {
694 nsIDOMNode_Release(node);
695 if(cspace) {
696 free_rangepoint(iter);
697 *iter = last_space;
698 return cspace;
701 iter->off--;
702 return '\n';
705 nsIDOMNode_Release(node);
707 }while(rangepoint_prev_node(iter));
709 if(cspace) {
710 free_rangepoint(iter);
711 *iter = last_space;
712 return cspace;
715 return 0;
718 static LONG move_by_chars(rangepoint_t *iter, LONG cnt)
720 LONG ret = 0;
722 if(cnt >= 0) {
723 while(ret < cnt && move_next_char(iter))
724 ret++;
725 }else {
726 while(ret > cnt && move_prev_char(iter))
727 ret--;
730 return ret;
733 static LONG find_prev_space(rangepoint_t *iter, BOOL first_space)
735 rangepoint_t prev;
736 WCHAR c;
738 init_rangepoint(&prev, iter->node, iter->off);
739 c = move_prev_char(&prev);
740 if(!c || (first_space && iswspace(c))) {
741 free_rangepoint(&prev);
742 return FALSE;
745 do {
746 free_rangepoint(iter);
747 init_rangepoint(iter, prev.node, prev.off);
748 c = move_prev_char(&prev);
749 }while(c && !iswspace(c));
751 free_rangepoint(&prev);
752 return TRUE;
755 static BOOL find_word_end(rangepoint_t *iter, BOOL is_collapsed)
757 rangepoint_t prev_iter;
758 WCHAR c;
759 BOOL ret = FALSE;
761 if(!is_collapsed) {
762 init_rangepoint(&prev_iter, iter->node, iter->off);
763 c = move_prev_char(&prev_iter);
764 free_rangepoint(&prev_iter);
765 if(iswspace(c))
766 return FALSE;
769 do {
770 init_rangepoint(&prev_iter, iter->node, iter->off);
771 c = move_next_char(iter);
772 if(c == '\n') {
773 free_rangepoint(iter);
774 *iter = prev_iter;
775 return ret;
777 if(!c) {
778 if(!ret)
779 ret = !rangepoint_cmp(iter, &prev_iter);
780 }else {
781 ret = TRUE;
783 free_rangepoint(&prev_iter);
784 }while(c && !iswspace(c));
786 return ret;
789 static LONG move_by_words(rangepoint_t *iter, LONG cnt)
791 LONG ret = 0;
793 if(cnt >= 0) {
794 WCHAR c;
796 while(ret < cnt && (c = move_next_char(iter))) {
797 if(iswspace(c))
798 ret++;
800 }else {
801 while(ret > cnt && find_prev_space(iter, FALSE))
802 ret--;
805 return ret;
808 static inline HTMLTxtRange *impl_from_IHTMLTxtRange(IHTMLTxtRange *iface)
810 return CONTAINING_RECORD(iface, HTMLTxtRange, IHTMLTxtRange_iface);
813 static HRESULT WINAPI HTMLTxtRange_QueryInterface(IHTMLTxtRange *iface, REFIID riid, void **ppv)
815 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
816 return IDispatchEx_QueryInterface(&This->dispex.IDispatchEx_iface, riid, ppv);
819 static ULONG WINAPI HTMLTxtRange_AddRef(IHTMLTxtRange *iface)
821 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
822 return IDispatchEx_AddRef(&This->dispex.IDispatchEx_iface);
825 static ULONG WINAPI HTMLTxtRange_Release(IHTMLTxtRange *iface)
827 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
828 return IDispatchEx_Release(&This->dispex.IDispatchEx_iface);
831 static HRESULT WINAPI HTMLTxtRange_GetTypeInfoCount(IHTMLTxtRange *iface, UINT *pctinfo)
833 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
835 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
838 static HRESULT WINAPI HTMLTxtRange_GetTypeInfo(IHTMLTxtRange *iface, UINT iTInfo,
839 LCID lcid, ITypeInfo **ppTInfo)
841 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
843 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
846 static HRESULT WINAPI HTMLTxtRange_GetIDsOfNames(IHTMLTxtRange *iface, REFIID riid,
847 LPOLESTR *rgszNames, UINT cNames,
848 LCID lcid, DISPID *rgDispId)
850 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
852 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames,
853 cNames, lcid, rgDispId);
856 static HRESULT WINAPI HTMLTxtRange_Invoke(IHTMLTxtRange *iface, DISPID dispIdMember,
857 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
858 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
860 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
862 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid,
863 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
866 static HRESULT WINAPI HTMLTxtRange_get_htmlText(IHTMLTxtRange *iface, BSTR *p)
868 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
870 TRACE("(%p)->(%p)\n", This, p);
872 *p = NULL;
874 if(This->nsrange) {
875 nsIDOMDocumentFragment *fragment;
876 nsresult nsres;
878 nsres = nsIDOMRange_CloneContents(This->nsrange, &fragment);
879 if(NS_SUCCEEDED(nsres)) {
880 const PRUnichar *nstext;
881 nsAString nsstr;
883 nsAString_Init(&nsstr, NULL);
884 nsnode_to_nsstring((nsIDOMNode*)fragment, &nsstr);
885 nsIDOMDocumentFragment_Release(fragment);
887 nsAString_GetData(&nsstr, &nstext);
888 *p = SysAllocString(nstext);
890 nsAString_Finish(&nsstr);
894 if(!*p) {
895 *p = SysAllocString(L"");
898 TRACE("return %s\n", debugstr_w(*p));
899 return S_OK;
902 static HRESULT WINAPI HTMLTxtRange_put_text(IHTMLTxtRange *iface, BSTR v)
904 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
905 nsIDOMText *text_node;
906 nsAString text_str;
907 nsresult nsres;
909 TRACE("(%p)->(%s)\n", This, debugstr_w(v));
911 if(!This->doc)
912 return MSHTML_E_NODOC;
914 nsAString_InitDepend(&text_str, v);
915 nsres = nsIDOMDocument_CreateTextNode(This->doc->dom_document, &text_str, &text_node);
916 nsAString_Finish(&text_str);
917 if(NS_FAILED(nsres)) {
918 ERR("CreateTextNode failed: %08lx\n", nsres);
919 return S_OK;
921 nsres = nsIDOMRange_DeleteContents(This->nsrange);
922 if(NS_FAILED(nsres))
923 ERR("DeleteContents failed: %08lx\n", nsres);
925 nsres = nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)text_node);
926 if(NS_FAILED(nsres))
927 ERR("InsertNode failed: %08lx\n", nsres);
929 nsres = nsIDOMRange_SetEndAfter(This->nsrange, (nsIDOMNode*)text_node);
930 if(NS_FAILED(nsres))
931 ERR("SetEndAfter failed: %08lx\n", nsres);
933 nsIDOMText_Release(text_node);
934 return IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_FALSE);
937 static HRESULT WINAPI HTMLTxtRange_get_text(IHTMLTxtRange *iface, BSTR *p)
939 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
940 wstrbuf_t buf;
942 TRACE("(%p)->(%p)\n", This, p);
944 *p = NULL;
945 if(!This->nsrange)
946 return S_OK;
948 if (!wstrbuf_init(&buf))
949 return E_OUTOFMEMORY;
950 range_to_string(This, &buf);
951 if (buf.buf)
952 *p = SysAllocString(buf.buf);
953 wstrbuf_finish(&buf);
955 TRACE("ret %s\n", debugstr_w(*p));
956 return S_OK;
959 static HRESULT WINAPI HTMLTxtRange_parentElement(IHTMLTxtRange *iface, IHTMLElement **parent)
961 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
962 nsIDOMNode *nsnode, *tmp;
963 HTMLDOMNode *node;
964 HRESULT hres;
966 TRACE("(%p)->(%p)\n", This, parent);
968 nsIDOMRange_GetCommonAncestorContainer(This->nsrange, &nsnode);
969 while(nsnode && get_node_type(nsnode) != ELEMENT_NODE) {
970 nsIDOMNode_GetParentNode(nsnode, &tmp);
971 nsIDOMNode_Release(nsnode);
972 nsnode = tmp;
975 if(!nsnode) {
976 *parent = NULL;
977 return S_OK;
980 hres = get_node(nsnode, TRUE, &node);
981 nsIDOMNode_Release(nsnode);
982 if(FAILED(hres))
983 return hres;
985 hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface, &IID_IHTMLElement, (void**)parent);
986 node_release(node);
987 return hres;
990 static HRESULT WINAPI HTMLTxtRange_duplicate(IHTMLTxtRange *iface, IHTMLTxtRange **Duplicate)
992 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
993 nsIDOMRange *nsrange = NULL;
994 HRESULT hres;
996 TRACE("(%p)->(%p)\n", This, Duplicate);
998 nsIDOMRange_CloneRange(This->nsrange, &nsrange);
999 hres = HTMLTxtRange_Create(This->doc, nsrange, Duplicate);
1000 nsIDOMRange_Release(nsrange);
1002 return hres;
1005 static HRESULT WINAPI HTMLTxtRange_inRange(IHTMLTxtRange *iface, IHTMLTxtRange *Range,
1006 VARIANT_BOOL *InRange)
1008 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1009 HTMLTxtRange *src_range;
1010 short nsret = 0;
1011 nsresult nsres;
1013 TRACE("(%p)->(%p %p)\n", This, Range, InRange);
1015 *InRange = VARIANT_FALSE;
1017 src_range = get_range_object(This->doc, Range);
1018 if(!src_range)
1019 return E_FAIL;
1021 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_START_TO_START,
1022 src_range->nsrange, &nsret);
1023 if(NS_SUCCEEDED(nsres) && nsret <= 0) {
1024 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_END_TO_END,
1025 src_range->nsrange, &nsret);
1026 if(NS_SUCCEEDED(nsres) && nsret >= 0)
1027 *InRange = VARIANT_TRUE;
1030 if(NS_FAILED(nsres))
1031 ERR("CompareBoundaryPoints failed: %08lx\n", nsres);
1033 return S_OK;
1036 static HRESULT WINAPI HTMLTxtRange_isEqual(IHTMLTxtRange *iface, IHTMLTxtRange *Range,
1037 VARIANT_BOOL *IsEqual)
1039 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1040 HTMLTxtRange *src_range;
1041 short nsret = 0;
1042 nsresult nsres;
1044 TRACE("(%p)->(%p %p)\n", This, Range, IsEqual);
1046 *IsEqual = VARIANT_FALSE;
1048 src_range = get_range_object(This->doc, Range);
1049 if(!src_range)
1050 return E_FAIL;
1052 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_START_TO_START,
1053 src_range->nsrange, &nsret);
1054 if(NS_SUCCEEDED(nsres) && !nsret) {
1055 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_END_TO_END,
1056 src_range->nsrange, &nsret);
1057 if(NS_SUCCEEDED(nsres) && !nsret)
1058 *IsEqual = VARIANT_TRUE;
1061 if(NS_FAILED(nsres))
1062 ERR("CompareBoundaryPoints failed: %08lx\n", nsres);
1064 return S_OK;
1067 static HRESULT WINAPI HTMLTxtRange_scrollIntoView(IHTMLTxtRange *iface, VARIANT_BOOL fStart)
1069 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1070 FIXME("(%p)->(%x)\n", This, fStart);
1071 return E_NOTIMPL;
1074 static HRESULT WINAPI HTMLTxtRange_collapse(IHTMLTxtRange *iface, VARIANT_BOOL Start)
1076 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1078 TRACE("(%p)->(%x)\n", This, Start);
1080 nsIDOMRange_Collapse(This->nsrange, Start != VARIANT_FALSE);
1081 return S_OK;
1084 static HRESULT WINAPI HTMLTxtRange_expand(IHTMLTxtRange *iface, BSTR Unit, VARIANT_BOOL *Success)
1086 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1087 range_unit_t unit;
1089 TRACE("(%p)->(%s %p)\n", This, debugstr_w(Unit), Success);
1091 unit = string_to_unit(Unit);
1092 if(unit == RU_UNKNOWN)
1093 return E_INVALIDARG;
1095 *Success = VARIANT_FALSE;
1097 switch(unit) {
1098 case RU_WORD: {
1099 rangepoint_t end, start;
1100 cpp_bool is_collapsed;
1102 get_start_point(This, &start);
1103 get_end_point(This, &end);
1105 nsIDOMRange_GetCollapsed(This->nsrange, &is_collapsed);
1107 if(find_word_end(&end, is_collapsed)) {
1108 set_end_point(This, &end);
1109 *Success = VARIANT_TRUE;
1112 if(find_prev_space(&start, TRUE)) {
1113 set_start_point(This, &start);
1114 *Success = VARIANT_TRUE;
1117 free_rangepoint(&end);
1118 free_rangepoint(&start);
1119 break;
1122 case RU_TEXTEDIT: {
1123 nsIDOMHTMLElement *nsbody = NULL;
1124 nsresult nsres;
1126 if(!This->doc->html_document) {
1127 FIXME("Not implemented for XML document\n");
1128 return E_NOTIMPL;
1131 nsres = nsIDOMHTMLDocument_GetBody(This->doc->html_document, &nsbody);
1132 if(NS_FAILED(nsres) || !nsbody) {
1133 ERR("Could not get body: %08lx\n", nsres);
1134 break;
1137 nsres = nsIDOMRange_SelectNodeContents(This->nsrange, (nsIDOMNode*)nsbody);
1138 nsIDOMHTMLElement_Release(nsbody);
1139 if(NS_FAILED(nsres)) {
1140 ERR("Collapse failed: %08lx\n", nsres);
1141 break;
1144 *Success = VARIANT_TRUE;
1145 break;
1148 default:
1149 FIXME("Unimplemented unit %s\n", debugstr_w(Unit));
1152 return S_OK;
1155 static HRESULT WINAPI HTMLTxtRange_move(IHTMLTxtRange *iface, BSTR Unit,
1156 LONG Count, LONG *ActualCount)
1158 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1159 range_unit_t unit;
1161 TRACE("(%p)->(%s %ld %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1163 unit = string_to_unit(Unit);
1164 if(unit == RU_UNKNOWN)
1165 return E_INVALIDARG;
1167 if(!Count) {
1168 *ActualCount = 0;
1169 return IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1172 switch(unit) {
1173 case RU_CHAR: {
1174 rangepoint_t start;
1176 get_start_point(This, &start);
1178 *ActualCount = move_by_chars(&start, Count);
1180 set_start_point(This, &start);
1181 IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1182 free_rangepoint(&start);
1183 break;
1186 case RU_WORD: {
1187 rangepoint_t start;
1189 get_start_point(This, &start);
1191 *ActualCount = move_by_words(&start, Count);
1193 set_start_point(This, &start);
1194 IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1195 free_rangepoint(&start);
1196 break;
1199 default:
1200 FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1203 TRACE("ret %ld\n", *ActualCount);
1204 return S_OK;
1207 static HRESULT WINAPI HTMLTxtRange_moveStart(IHTMLTxtRange *iface, BSTR Unit,
1208 LONG Count, LONG *ActualCount)
1210 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1211 range_unit_t unit;
1213 TRACE("(%p)->(%s %ld %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1215 unit = string_to_unit(Unit);
1216 if(unit == RU_UNKNOWN)
1217 return E_INVALIDARG;
1219 if(!Count) {
1220 *ActualCount = 0;
1221 return S_OK;
1224 switch(unit) {
1225 case RU_CHAR: {
1226 rangepoint_t start;
1228 get_start_point(This, &start);
1230 *ActualCount = move_by_chars(&start, Count);
1232 set_start_point(This, &start);
1233 free_rangepoint(&start);
1234 break;
1237 default:
1238 FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1239 return E_NOTIMPL;
1242 return S_OK;
1245 static HRESULT WINAPI HTMLTxtRange_moveEnd(IHTMLTxtRange *iface, BSTR Unit,
1246 LONG Count, LONG *ActualCount)
1248 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1249 range_unit_t unit;
1251 TRACE("(%p)->(%s %ld %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1253 unit = string_to_unit(Unit);
1254 if(unit == RU_UNKNOWN)
1255 return E_INVALIDARG;
1257 if(!Count) {
1258 *ActualCount = 0;
1259 return S_OK;
1262 switch(unit) {
1263 case RU_CHAR: {
1264 rangepoint_t end;
1266 get_end_point(This, &end);
1268 *ActualCount = move_by_chars(&end, Count);
1270 set_end_point(This, &end);
1271 free_rangepoint(&end);
1272 break;
1275 default:
1276 FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1279 return S_OK;
1282 static HRESULT WINAPI HTMLTxtRange_select(IHTMLTxtRange *iface)
1284 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1285 nsISelection *nsselection;
1286 nsresult nsres;
1288 TRACE("(%p)\n", This);
1290 nsres = nsIDOMWindow_GetSelection(This->doc->outer_window->nswindow, &nsselection);
1291 if(NS_FAILED(nsres)) {
1292 ERR("GetSelection failed: %08lx\n", nsres);
1293 return E_FAIL;
1296 nsISelection_RemoveAllRanges(nsselection);
1297 nsISelection_AddRange(nsselection, This->nsrange);
1298 nsISelection_Release(nsselection);
1299 return S_OK;
1302 static HRESULT WINAPI HTMLTxtRange_pasteHTML(IHTMLTxtRange *iface, BSTR html)
1304 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1305 nsIDOMDocumentFragment *doc_frag;
1306 nsAString nsstr;
1307 nsresult nsres;
1309 TRACE("(%p)->(%s)\n", This, debugstr_w(html));
1311 nsres = nsIDOMRange_Collapse(This->nsrange, TRUE);
1312 assert(nsres == NS_OK);
1314 nsAString_InitDepend(&nsstr, html);
1315 nsres = nsIDOMRange_CreateContextualFragment(This->nsrange, &nsstr, &doc_frag);
1316 nsAString_Finish(&nsstr);
1317 if(NS_FAILED(nsres)) {
1318 ERR("CreateContextualFragment failed: %08lx\n", nsres);
1319 return E_FAIL;
1322 nsres = nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)doc_frag);
1323 nsIDOMDocumentFragment_Release(doc_frag);
1324 if(NS_FAILED(nsres)) {
1325 ERR("InsertNode failed: %08lx\n", nsres);
1326 return E_FAIL;
1329 nsres = nsIDOMRange_Collapse(This->nsrange, FALSE);
1330 assert(nsres == NS_OK);
1331 return S_OK;
1334 static HRESULT WINAPI HTMLTxtRange_moveToElementText(IHTMLTxtRange *iface, IHTMLElement *element)
1336 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1337 HTMLElement *elem;
1338 nsresult nsres;
1340 TRACE("(%p)->(%p)\n", This, element);
1342 elem = unsafe_impl_from_IHTMLElement(element);
1343 if(!elem)
1344 return E_INVALIDARG;
1346 nsres = nsIDOMRange_SelectNodeContents(This->nsrange, elem->node.nsnode);
1347 if(NS_FAILED(nsres)) {
1348 ERR("SelectNodeContents failed: %08lx\n", nsres);
1349 return E_FAIL;
1352 return S_OK;
1355 static HRESULT WINAPI HTMLTxtRange_setEndPoint(IHTMLTxtRange *iface, BSTR how,
1356 IHTMLTxtRange *SourceRange)
1358 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1359 HTMLTxtRange *src_range;
1360 nsIDOMNode *ref_node;
1361 LONG ref_offset;
1362 BOOL set_start;
1363 int how_type;
1364 INT16 cmp;
1365 nsresult nsres;
1367 TRACE("(%p)->(%s %p)\n", This, debugstr_w(how), SourceRange);
1369 how_type = string_to_nscmptype(how);
1370 if(how_type == -1)
1371 return E_INVALIDARG;
1373 src_range = get_range_object(This->doc, SourceRange);
1374 if(!src_range)
1375 return E_FAIL;
1377 switch(how_type) {
1378 case NS_START_TO_START:
1379 case NS_END_TO_START:
1380 nsres = nsIDOMRange_GetStartContainer(src_range->nsrange, &ref_node);
1381 assert(nsres == NS_OK);
1383 nsres = nsIDOMRange_GetStartOffset(src_range->nsrange, &ref_offset);
1384 assert(nsres == NS_OK);
1386 set_start = how_type == NS_START_TO_START;
1387 break;
1388 case NS_END_TO_END:
1389 case NS_START_TO_END:
1390 nsres = nsIDOMRange_GetEndContainer(src_range->nsrange, &ref_node);
1391 assert(nsres == NS_OK);
1393 nsres = nsIDOMRange_GetEndOffset(src_range->nsrange, &ref_offset);
1394 assert(nsres == NS_OK);
1396 set_start = how_type == NS_START_TO_END;
1397 break;
1398 DEFAULT_UNREACHABLE;
1401 nsres = nsIDOMRange_ComparePoint(This->nsrange, ref_node, ref_offset, &cmp);
1402 assert(nsres == NS_OK);
1404 if(set_start) {
1405 if(cmp <= 0) {
1406 nsres = nsIDOMRange_SetStart(This->nsrange, ref_node, ref_offset);
1407 }else {
1408 nsres = nsIDOMRange_Collapse(This->nsrange, FALSE);
1409 assert(nsres == NS_OK);
1411 nsres = nsIDOMRange_SetEnd(This->nsrange, ref_node, ref_offset);
1413 }else {
1414 if(cmp >= 0) {
1415 nsres = nsIDOMRange_SetEnd(This->nsrange, ref_node, ref_offset);
1416 }else {
1417 nsres = nsIDOMRange_Collapse(This->nsrange, TRUE);
1418 assert(nsres == NS_OK);
1420 nsres = nsIDOMRange_SetStart(This->nsrange, ref_node, ref_offset);
1423 assert(nsres == NS_OK);
1425 nsIDOMNode_Release(ref_node);
1426 return S_OK;
1429 static HRESULT WINAPI HTMLTxtRange_compareEndPoints(IHTMLTxtRange *iface, BSTR how,
1430 IHTMLTxtRange *SourceRange, LONG *ret)
1432 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1433 HTMLTxtRange *src_range;
1434 short nsret = 0;
1435 int nscmpt;
1436 nsresult nsres;
1438 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(how), SourceRange, ret);
1440 nscmpt = string_to_nscmptype(how);
1441 if(nscmpt == -1)
1442 return E_INVALIDARG;
1444 src_range = get_range_object(This->doc, SourceRange);
1445 if(!src_range)
1446 return E_FAIL;
1448 nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, nscmpt, src_range->nsrange, &nsret);
1449 if(NS_FAILED(nsres))
1450 ERR("CompareBoundaryPoints failed: %08lx\n", nsres);
1452 *ret = nsret;
1453 return S_OK;
1456 static HRESULT WINAPI HTMLTxtRange_findText(IHTMLTxtRange *iface, BSTR String,
1457 LONG count, LONG Flags, VARIANT_BOOL *Success)
1459 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1460 FIXME("(%p)->(%s %ld %08lx %p)\n", This, debugstr_w(String), count, Flags, Success);
1461 return E_NOTIMPL;
1464 static HRESULT WINAPI HTMLTxtRange_moveToPoint(IHTMLTxtRange *iface, LONG x, LONG y)
1466 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1467 FIXME("(%p)->(%ld %ld)\n", This, x, y);
1468 return E_NOTIMPL;
1471 static HRESULT WINAPI HTMLTxtRange_getBookmark(IHTMLTxtRange *iface, BSTR *Bookmark)
1473 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1474 FIXME("(%p)->(%p)\n", This, Bookmark);
1475 return E_NOTIMPL;
1478 static HRESULT WINAPI HTMLTxtRange_moveToBookmark(IHTMLTxtRange *iface, BSTR Bookmark,
1479 VARIANT_BOOL *Success)
1481 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1482 FIXME("(%p)->(%s %p)\n", This, debugstr_w(Bookmark), Success);
1483 return E_NOTIMPL;
1486 static HRESULT WINAPI HTMLTxtRange_queryCommandSupported(IHTMLTxtRange *iface, BSTR cmdID,
1487 VARIANT_BOOL *pfRet)
1489 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1490 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1491 return E_NOTIMPL;
1494 static HRESULT WINAPI HTMLTxtRange_queryCommandEnabled(IHTMLTxtRange *iface, BSTR cmdID,
1495 VARIANT_BOOL *pfRet)
1497 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1498 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1499 return E_NOTIMPL;
1502 static HRESULT WINAPI HTMLTxtRange_queryCommandState(IHTMLTxtRange *iface, BSTR cmdID,
1503 VARIANT_BOOL *pfRet)
1505 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1506 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1507 return E_NOTIMPL;
1510 static HRESULT WINAPI HTMLTxtRange_queryCommandIndeterm(IHTMLTxtRange *iface, BSTR cmdID,
1511 VARIANT_BOOL *pfRet)
1513 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1514 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1515 return E_NOTIMPL;
1518 static HRESULT WINAPI HTMLTxtRange_queryCommandText(IHTMLTxtRange *iface, BSTR cmdID,
1519 BSTR *pcmdText)
1521 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1522 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pcmdText);
1523 return E_NOTIMPL;
1526 static HRESULT WINAPI HTMLTxtRange_queryCommandValue(IHTMLTxtRange *iface, BSTR cmdID,
1527 VARIANT *pcmdValue)
1529 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1530 FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pcmdValue);
1531 return E_NOTIMPL;
1534 static HRESULT WINAPI HTMLTxtRange_execCommand(IHTMLTxtRange *iface, BSTR cmdID,
1535 VARIANT_BOOL showUI, VARIANT value, VARIANT_BOOL *pfRet)
1537 HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1538 FIXME("(%p)->(%s %x v %p)\n", This, debugstr_w(cmdID), showUI, pfRet);
1539 return E_NOTIMPL;
1542 static HRESULT WINAPI HTMLTxtRange_execCommandShowHelp(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 const IHTMLTxtRangeVtbl HTMLTxtRangeVtbl = {
1551 HTMLTxtRange_QueryInterface,
1552 HTMLTxtRange_AddRef,
1553 HTMLTxtRange_Release,
1554 HTMLTxtRange_GetTypeInfoCount,
1555 HTMLTxtRange_GetTypeInfo,
1556 HTMLTxtRange_GetIDsOfNames,
1557 HTMLTxtRange_Invoke,
1558 HTMLTxtRange_get_htmlText,
1559 HTMLTxtRange_put_text,
1560 HTMLTxtRange_get_text,
1561 HTMLTxtRange_parentElement,
1562 HTMLTxtRange_duplicate,
1563 HTMLTxtRange_inRange,
1564 HTMLTxtRange_isEqual,
1565 HTMLTxtRange_scrollIntoView,
1566 HTMLTxtRange_collapse,
1567 HTMLTxtRange_expand,
1568 HTMLTxtRange_move,
1569 HTMLTxtRange_moveStart,
1570 HTMLTxtRange_moveEnd,
1571 HTMLTxtRange_select,
1572 HTMLTxtRange_pasteHTML,
1573 HTMLTxtRange_moveToElementText,
1574 HTMLTxtRange_setEndPoint,
1575 HTMLTxtRange_compareEndPoints,
1576 HTMLTxtRange_findText,
1577 HTMLTxtRange_moveToPoint,
1578 HTMLTxtRange_getBookmark,
1579 HTMLTxtRange_moveToBookmark,
1580 HTMLTxtRange_queryCommandSupported,
1581 HTMLTxtRange_queryCommandEnabled,
1582 HTMLTxtRange_queryCommandState,
1583 HTMLTxtRange_queryCommandIndeterm,
1584 HTMLTxtRange_queryCommandText,
1585 HTMLTxtRange_queryCommandValue,
1586 HTMLTxtRange_execCommand,
1587 HTMLTxtRange_execCommandShowHelp
1590 static inline HTMLTxtRange *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
1592 return CONTAINING_RECORD(iface, HTMLTxtRange, IOleCommandTarget_iface);
1595 static HRESULT WINAPI RangeCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
1597 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1598 return IHTMLTxtRange_QueryInterface(&This->IHTMLTxtRange_iface, riid, ppv);
1601 static ULONG WINAPI RangeCommandTarget_AddRef(IOleCommandTarget *iface)
1603 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1604 return IHTMLTxtRange_AddRef(&This->IHTMLTxtRange_iface);
1607 static ULONG WINAPI RangeCommandTarget_Release(IOleCommandTarget *iface)
1609 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1610 return IHTMLTxtRange_Release(&This->IHTMLTxtRange_iface);
1613 static HRESULT WINAPI RangeCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1614 ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
1616 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1617 FIXME("(%p)->(%s %ld %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
1618 return E_NOTIMPL;
1621 static HRESULT exec_indent(HTMLTxtRange *This, VARIANT *in, VARIANT *out)
1623 nsIDOMElement *blockquote_elem, *p_elem;
1624 nsIDOMDocumentFragment *fragment;
1625 nsIDOMNode *tmp;
1627 TRACE("(%p)->(%p %p)\n", This, in, out);
1629 if(!This->doc->dom_document) {
1630 WARN("NULL dom_document\n");
1631 return E_NOTIMPL;
1634 create_nselem(This->doc, L"BLOCKQUOTE", &blockquote_elem);
1635 create_nselem(This->doc, L"P", &p_elem);
1637 nsIDOMRange_ExtractContents(This->nsrange, &fragment);
1638 nsIDOMElement_AppendChild(p_elem, (nsIDOMNode*)fragment, &tmp);
1639 nsIDOMDocumentFragment_Release(fragment);
1640 nsIDOMNode_Release(tmp);
1642 nsIDOMElement_AppendChild(blockquote_elem, (nsIDOMNode*)p_elem, &tmp);
1643 nsIDOMElement_Release(p_elem);
1644 nsIDOMNode_Release(tmp);
1646 nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)blockquote_elem);
1647 nsIDOMElement_Release(blockquote_elem);
1649 return S_OK;
1652 static HRESULT WINAPI RangeCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1653 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1655 HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1657 TRACE("(%p)->(%s %ld %lx %p %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID,
1658 nCmdexecopt, pvaIn, pvaOut);
1660 if(pguidCmdGroup && IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
1661 switch(nCmdID) {
1662 case IDM_INDENT:
1663 return exec_indent(This, pvaIn, pvaOut);
1664 default:
1665 FIXME("Unsupported cmdid %ld of CGID_MSHTML\n", nCmdID);
1667 }else {
1668 FIXME("Unsupported cmd %ld of group %s\n", nCmdID, debugstr_guid(pguidCmdGroup));
1671 return E_NOTIMPL;
1674 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
1675 RangeCommandTarget_QueryInterface,
1676 RangeCommandTarget_AddRef,
1677 RangeCommandTarget_Release,
1678 RangeCommandTarget_QueryStatus,
1679 RangeCommandTarget_Exec
1682 static inline HTMLTxtRange *HTMLTxtRange_from_DispatchEx(DispatchEx *iface)
1684 return CONTAINING_RECORD(iface, HTMLTxtRange, dispex);
1687 static void *HTMLTxtRange_query_interface(DispatchEx *dispex, REFIID riid)
1689 HTMLTxtRange *This = HTMLTxtRange_from_DispatchEx(dispex);
1691 if(IsEqualGUID(&IID_IHTMLTxtRange, riid))
1692 return &This->IHTMLTxtRange_iface;
1693 if(IsEqualGUID(&IID_IOleCommandTarget, riid))
1694 return &This->IOleCommandTarget_iface;
1696 return NULL;
1699 static void HTMLTxtRange_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
1701 HTMLTxtRange *This = HTMLTxtRange_from_DispatchEx(dispex);
1702 if(This->nsrange)
1703 note_cc_edge((nsISupports*)This->nsrange, "nsrange", cb);
1706 static void HTMLTxtRange_unlink(DispatchEx *dispex)
1708 HTMLTxtRange *This = HTMLTxtRange_from_DispatchEx(dispex);
1709 unlink_ref(&This->nsrange);
1710 if(This->doc) {
1711 This->doc = NULL;
1712 list_remove(&This->entry);
1716 static void HTMLTxtRange_destructor(DispatchEx *dispex)
1718 HTMLTxtRange *This = HTMLTxtRange_from_DispatchEx(dispex);
1719 free(This);
1722 static const dispex_static_data_vtbl_t HTMLTxtRange_dispex_vtbl = {
1723 .query_interface = HTMLTxtRange_query_interface,
1724 .destructor = HTMLTxtRange_destructor,
1725 .traverse = HTMLTxtRange_traverse,
1726 .unlink = HTMLTxtRange_unlink
1729 static const tid_t HTMLTxtRange_iface_tids[] = {
1730 IHTMLTxtRange_tid,
1733 static dispex_static_data_t HTMLTxtRange_dispex = {
1734 "TextRange",
1735 &HTMLTxtRange_dispex_vtbl,
1736 IHTMLTxtRange_tid,
1737 HTMLTxtRange_iface_tids
1740 HRESULT HTMLTxtRange_Create(HTMLDocumentNode *doc, nsIDOMRange *nsrange, IHTMLTxtRange **p)
1742 HTMLTxtRange *ret;
1744 ret = malloc(sizeof(HTMLTxtRange));
1745 if(!ret)
1746 return E_OUTOFMEMORY;
1748 init_dispatch(&ret->dispex, &HTMLTxtRange_dispex, dispex_compat_mode(&doc->node.event_target.dispex));
1750 ret->IHTMLTxtRange_iface.lpVtbl = &HTMLTxtRangeVtbl;
1751 ret->IOleCommandTarget_iface.lpVtbl = &OleCommandTargetVtbl;
1753 if(nsrange)
1754 nsIDOMRange_AddRef(nsrange);
1755 ret->nsrange = nsrange;
1757 ret->doc = doc;
1758 list_add_head(&doc->range_list, &ret->entry);
1760 *p = &ret->IHTMLTxtRange_iface;
1761 return S_OK;
1764 static inline HTMLDOMRange *impl_from_IHTMLDOMRange(IHTMLDOMRange *iface)
1766 return CONTAINING_RECORD(iface, HTMLDOMRange, IHTMLDOMRange_iface);
1769 static HRESULT WINAPI HTMLDOMRange_QueryInterface(IHTMLDOMRange *iface, REFIID riid, void **ppv)
1771 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1772 return IDispatchEx_QueryInterface(&This->dispex.IDispatchEx_iface, riid, ppv);
1775 static ULONG WINAPI HTMLDOMRange_AddRef(IHTMLDOMRange *iface)
1777 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1778 return IDispatchEx_AddRef(&This->dispex.IDispatchEx_iface);
1781 static ULONG WINAPI HTMLDOMRange_Release(IHTMLDOMRange *iface)
1783 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1784 return IDispatchEx_Release(&This->dispex.IDispatchEx_iface);
1787 static HRESULT WINAPI HTMLDOMRange_GetTypeInfoCount(IHTMLDOMRange *iface, UINT *pctinfo)
1789 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1791 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1794 static HRESULT WINAPI HTMLDOMRange_GetTypeInfo(IHTMLDOMRange *iface, UINT iTInfo,
1795 LCID lcid, ITypeInfo **ppTInfo)
1797 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1799 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1802 static HRESULT WINAPI HTMLDOMRange_GetIDsOfNames(IHTMLDOMRange *iface, REFIID riid,
1803 LPOLESTR *rgszNames, UINT cNames,
1804 LCID lcid, DISPID *rgDispId)
1806 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1808 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames,
1809 cNames, lcid, rgDispId);
1812 static HRESULT WINAPI HTMLDOMRange_Invoke(IHTMLDOMRange *iface, DISPID dispIdMember,
1813 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1814 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1816 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1818 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid,
1819 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1822 static HRESULT WINAPI HTMLDOMRange_get_startContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1824 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1825 FIXME("(%p)->(%p)\n", This, p);
1826 return E_NOTIMPL;
1829 static HRESULT WINAPI HTMLDOMRange_get_startOffset(IHTMLDOMRange *iface, LONG *p)
1831 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1832 FIXME("(%p)->(%p)\n", This, p);
1833 return E_NOTIMPL;
1836 static HRESULT WINAPI HTMLDOMRange_get_endContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1838 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1839 FIXME("(%p)->(%p)\n", This, p);
1840 return E_NOTIMPL;
1843 static HRESULT WINAPI HTMLDOMRange_get_endOffset(IHTMLDOMRange *iface, LONG *p)
1845 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1846 FIXME("(%p)->(%p)\n", This, p);
1847 return E_NOTIMPL;
1850 static HRESULT WINAPI HTMLDOMRange_get_collapsed(IHTMLDOMRange *iface, VARIANT_BOOL *p)
1852 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1853 FIXME("(%p)->(%p)\n", This, p);
1854 return E_NOTIMPL;
1857 static HRESULT WINAPI HTMLDOMRange_get_commonAncestorContainer(IHTMLDOMRange *iface, IHTMLDOMNode **p)
1859 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1860 FIXME("(%p)->(%p)\n", This, p);
1861 return E_NOTIMPL;
1864 static HRESULT WINAPI HTMLDOMRange_setStart(IHTMLDOMRange *iface, IDispatch *node, LONG offset)
1866 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1867 FIXME("(%p)->(%p, %ld)\n", This, node, offset);
1868 return E_NOTIMPL;
1871 static HRESULT WINAPI HTMLDOMRange_setEnd(IHTMLDOMRange *iface, IDispatch *node, LONG offset)
1873 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1874 FIXME("(%p)->(%p, %ld)\n", This, node, offset);
1875 return E_NOTIMPL;
1878 static HRESULT WINAPI HTMLDOMRange_setStartBefore(IHTMLDOMRange *iface, IDispatch *node)
1880 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1881 FIXME("(%p)->(%p)\n", This, node);
1882 return E_NOTIMPL;
1885 static HRESULT WINAPI HTMLDOMRange_setStartAfter(IHTMLDOMRange *iface, IDispatch *node)
1887 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1888 FIXME("(%p)->(%p)\n", This, node);
1889 return E_NOTIMPL;
1892 static HRESULT WINAPI HTMLDOMRange_setEndBefore(IHTMLDOMRange *iface, IDispatch *node)
1894 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1895 FIXME("(%p)->(%p)\n", This, node);
1896 return E_NOTIMPL;
1899 static HRESULT WINAPI HTMLDOMRange_setEndAfter(IHTMLDOMRange *iface, IDispatch *node)
1901 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1902 FIXME("(%p)->(%p)\n", This, node);
1903 return E_NOTIMPL;
1906 static HRESULT WINAPI HTMLDOMRange_collapse(IHTMLDOMRange *iface, VARIANT_BOOL tostart)
1908 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1909 FIXME("(%p)->(%x)\n", This, tostart);
1910 return E_NOTIMPL;
1913 static HRESULT WINAPI HTMLDOMRange_selectNode(IHTMLDOMRange *iface, IDispatch *node)
1915 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1916 FIXME("(%p)->(%p)\n", This, node);
1917 return E_NOTIMPL;
1920 static HRESULT WINAPI HTMLDOMRange_selectNodeContents(IHTMLDOMRange *iface, IDispatch *node)
1922 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1923 FIXME("(%p)->(%p)\n", This, node);
1924 return E_NOTIMPL;
1927 static HRESULT WINAPI HTMLDOMRange_compareBoundaryPoints(IHTMLDOMRange *iface, short how,
1928 IDispatch *src_range, LONG *result)
1930 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1931 FIXME("(%p)->(%x, %p, %p)\n", This, how, src_range, result);
1932 return E_NOTIMPL;
1935 static HRESULT WINAPI HTMLDOMRange_deleteContents(IHTMLDOMRange *iface)
1937 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1938 FIXME("(%p)\n", This);
1939 return E_NOTIMPL;
1942 static HRESULT WINAPI HTMLDOMRange_extractContents(IHTMLDOMRange *iface, IDispatch **p)
1944 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1945 FIXME("(%p)->(%p)\n", This, p);
1946 return E_NOTIMPL;
1949 static HRESULT WINAPI HTMLDOMRange_cloneContents(IHTMLDOMRange *iface, IDispatch **p)
1951 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1952 FIXME("(%p)->(%p)\n", This, p);
1953 return E_NOTIMPL;
1956 static HRESULT WINAPI HTMLDOMRange_insertNode(IHTMLDOMRange *iface, IDispatch *node)
1958 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1959 FIXME("(%p)->(%p)\n", This, node);
1960 return E_NOTIMPL;
1963 static HRESULT WINAPI HTMLDOMRange_surroundContents(IHTMLDOMRange *iface, IDispatch *parent)
1965 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1966 FIXME("(%p)->(%p)\n", This, parent);
1967 return E_NOTIMPL;
1970 static HRESULT WINAPI HTMLDOMRange_cloneRange(IHTMLDOMRange *iface, IHTMLDOMRange **p)
1972 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1973 FIXME("(%p)->(%p)\n", This, p);
1974 return E_NOTIMPL;
1977 static HRESULT WINAPI HTMLDOMRange_toString(IHTMLDOMRange *iface, BSTR *p)
1979 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1980 FIXME("(%p)->(%p)\n", This, p);
1981 return E_NOTIMPL;
1984 static HRESULT WINAPI HTMLDOMRange_detach(IHTMLDOMRange *iface)
1986 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1987 FIXME("(%p)\n", This);
1988 return E_NOTIMPL;
1991 static HRESULT WINAPI HTMLDOMRange_getClientRects(IHTMLDOMRange *iface, IHTMLRectCollection **p)
1993 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
1994 FIXME("(%p)->(%p)\n", This, p);
1995 return E_NOTIMPL;
1998 static HRESULT WINAPI HTMLDOMRange_getBoundingClientRect(IHTMLDOMRange *iface, IHTMLRect **p)
2000 HTMLDOMRange *This = impl_from_IHTMLDOMRange(iface);
2001 FIXME("(%p)->(%p)\n", This, p);
2002 return E_NOTIMPL;
2005 static const IHTMLDOMRangeVtbl HTMLDOMRangeVtbl = {
2006 HTMLDOMRange_QueryInterface,
2007 HTMLDOMRange_AddRef,
2008 HTMLDOMRange_Release,
2009 HTMLDOMRange_GetTypeInfoCount,
2010 HTMLDOMRange_GetTypeInfo,
2011 HTMLDOMRange_GetIDsOfNames,
2012 HTMLDOMRange_Invoke,
2013 HTMLDOMRange_get_startContainer,
2014 HTMLDOMRange_get_startOffset,
2015 HTMLDOMRange_get_endContainer,
2016 HTMLDOMRange_get_endOffset,
2017 HTMLDOMRange_get_collapsed,
2018 HTMLDOMRange_get_commonAncestorContainer,
2019 HTMLDOMRange_setStart,
2020 HTMLDOMRange_setEnd,
2021 HTMLDOMRange_setStartBefore,
2022 HTMLDOMRange_setStartAfter,
2023 HTMLDOMRange_setEndBefore,
2024 HTMLDOMRange_setEndAfter,
2025 HTMLDOMRange_collapse,
2026 HTMLDOMRange_selectNode,
2027 HTMLDOMRange_selectNodeContents,
2028 HTMLDOMRange_compareBoundaryPoints,
2029 HTMLDOMRange_deleteContents,
2030 HTMLDOMRange_extractContents,
2031 HTMLDOMRange_cloneContents,
2032 HTMLDOMRange_insertNode,
2033 HTMLDOMRange_surroundContents,
2034 HTMLDOMRange_cloneRange,
2035 HTMLDOMRange_toString,
2036 HTMLDOMRange_detach,
2037 HTMLDOMRange_getClientRects,
2038 HTMLDOMRange_getBoundingClientRect,
2041 static inline HTMLDOMRange *HTMLDOMRange_from_DispatchEx(DispatchEx *iface)
2043 return CONTAINING_RECORD(iface, HTMLDOMRange, dispex);
2046 static void *HTMLDOMRange_query_interface(DispatchEx *dispex, REFIID riid)
2048 HTMLDOMRange *This = HTMLDOMRange_from_DispatchEx(dispex);
2050 if(IsEqualGUID(&IID_IUnknown, riid))
2051 return &This->IHTMLDOMRange_iface;
2052 if(IsEqualGUID(&IID_IHTMLDOMRange, riid))
2053 return &This->IHTMLDOMRange_iface;
2055 return NULL;
2058 static void HTMLDOMRange_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
2060 HTMLDOMRange *This = HTMLDOMRange_from_DispatchEx(dispex);
2061 if(This->nsrange)
2062 note_cc_edge((nsISupports*)This->nsrange, "nsrange", cb);
2065 static void HTMLDOMRange_unlink(DispatchEx *dispex)
2067 HTMLDOMRange *This = HTMLDOMRange_from_DispatchEx(dispex);
2068 unlink_ref(&This->nsrange);
2071 static void HTMLDOMRange_destructor(DispatchEx *dispex)
2073 HTMLDOMRange *This = HTMLDOMRange_from_DispatchEx(dispex);
2074 free(This);
2077 static const dispex_static_data_vtbl_t HTMLDOMRange_dispex_vtbl = {
2078 .query_interface = HTMLDOMRange_query_interface,
2079 .destructor = HTMLDOMRange_destructor,
2080 .traverse = HTMLDOMRange_traverse,
2081 .unlink = HTMLDOMRange_unlink
2084 static const tid_t HTMLDOMRange_iface_tids[] = {
2085 IHTMLDOMRange_tid,
2089 static dispex_static_data_t HTMLDOMRange_dispex = {
2090 "Range",
2091 &HTMLDOMRange_dispex_vtbl,
2092 DispHTMLDOMRange_tid,
2093 HTMLDOMRange_iface_tids
2096 HRESULT create_dom_range(nsIDOMRange *nsrange, compat_mode_t compat_mode, IHTMLDOMRange **p)
2098 HTMLDOMRange *ret;
2100 ret = malloc(sizeof(*ret));
2101 if(!ret)
2102 return E_OUTOFMEMORY;
2104 init_dispatch(&ret->dispex, &HTMLDOMRange_dispex, compat_mode);
2106 ret->IHTMLDOMRange_iface.lpVtbl = &HTMLDOMRangeVtbl;
2108 if(nsrange)
2109 nsIDOMRange_AddRef(nsrange);
2110 ret->nsrange = nsrange;
2112 *p = &ret->IHTMLDOMRange_iface;
2113 return S_OK;
2116 void detach_ranges(HTMLDocumentNode *This)
2118 HTMLTxtRange *iter, *next;
2120 LIST_FOR_EACH_ENTRY_SAFE(iter, next, &This->range_list, HTMLTxtRange, entry) {
2121 iter->doc = NULL;
2122 list_remove(&iter->entry);
2126 typedef struct {
2127 IMarkupPointer2 IMarkupPointer2_iface;
2128 LONG ref;
2129 } MarkupPointer;
2131 static inline MarkupPointer *impl_from_IMarkupPointer2(IMarkupPointer2 *iface)
2133 return CONTAINING_RECORD(iface, MarkupPointer, IMarkupPointer2_iface);
2136 static HRESULT WINAPI MarkupPointer2_QueryInterface(IMarkupPointer2 *iface, REFIID riid, void **ppv)
2138 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2140 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
2142 if(IsEqualGUID(&IID_IUnknown, riid)) {
2143 *ppv = &This->IMarkupPointer2_iface;
2144 }else if(IsEqualGUID(&IID_IMarkupPointer, riid)) {
2145 *ppv = &This->IMarkupPointer2_iface;
2146 }else if(IsEqualGUID(&IID_IMarkupPointer2, riid)) {
2147 *ppv = &This->IMarkupPointer2_iface;
2148 }else {
2149 *ppv = NULL;
2150 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2151 return E_NOINTERFACE;
2154 IUnknown_AddRef((IUnknown*)*ppv);
2155 return S_OK;
2158 static ULONG WINAPI MarkupPointer2_AddRef(IMarkupPointer2 *iface)
2160 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2161 LONG ref = InterlockedIncrement(&This->ref);
2163 TRACE("(%p) ref=%ld\n", This, ref);
2165 return ref;
2168 static ULONG WINAPI MarkupPointer2_Release(IMarkupPointer2 *iface)
2170 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2171 LONG ref = InterlockedDecrement(&This->ref);
2173 TRACE("(%p) ref=%ld\n", This, ref);
2175 if(!ref)
2176 free(This);
2178 return ref;
2181 static HRESULT WINAPI MarkupPointer2_OwningDoc(IMarkupPointer2 *iface, IHTMLDocument2 **p)
2183 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2184 FIXME("(%p)->(%p)\n", This, p);
2185 return E_NOTIMPL;
2188 static HRESULT WINAPI MarkupPointer2_Gravity(IMarkupPointer2 *iface, POINTER_GRAVITY *p)
2190 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2191 FIXME("(%p)->(%p)\n", This, p);
2192 return E_NOTIMPL;
2195 static HRESULT WINAPI MarkupPointer2_SetGravity(IMarkupPointer2 *iface, POINTER_GRAVITY gravity)
2197 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2198 FIXME("(%p)->(%u)\n", This, gravity);
2199 return E_NOTIMPL;
2202 static HRESULT WINAPI MarkupPointer2_Cling(IMarkupPointer2 *iface, BOOL *p)
2204 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2205 FIXME("(%p)->(%p)\n", This, p);
2206 return E_NOTIMPL;
2209 static HRESULT WINAPI MarkupPointer2_SetCling(IMarkupPointer2 *iface, BOOL cling)
2211 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2212 FIXME("(%p)->(%x)\n", This, cling);
2213 return E_NOTIMPL;
2216 static HRESULT WINAPI MarkupPointer2_Unposition(IMarkupPointer2 *iface)
2218 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2219 FIXME("(%p)\n", This);
2220 return E_NOTIMPL;
2223 static HRESULT WINAPI MarkupPointer2_IsPositioned(IMarkupPointer2 *iface, BOOL *p)
2225 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2226 FIXME("(%p)->(%p)\n", This, p);
2227 return E_NOTIMPL;
2230 static HRESULT WINAPI MarkupPointer2_GetContainer(IMarkupPointer2 *iface, IMarkupContainer **p)
2232 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2233 FIXME("(%p)->(%p)\n", This, p);
2234 return E_NOTIMPL;
2237 static HRESULT WINAPI MarkupPointer2_MoveAdjacentToElement(IMarkupPointer2 *iface, IHTMLElement *element, ELEMENT_ADJACENCY adj)
2239 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2240 FIXME("(%p)->(%p %u)\n", This, element, adj);
2241 return E_NOTIMPL;
2244 static HRESULT WINAPI MarkupPointer2_MoveToPointer(IMarkupPointer2 *iface, IMarkupPointer *pointer)
2246 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2247 FIXME("(%p)->(%p)\n", This, pointer);
2248 return E_NOTIMPL;
2251 static HRESULT WINAPI MarkupPointer2_MoveToContainer(IMarkupPointer2 *iface, IMarkupContainer *container, BOOL at_start)
2253 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2254 FIXME("(%p)->(%p %x)\n", This, container, at_start);
2255 return E_NOTIMPL;
2258 static HRESULT WINAPI MarkupPointer2_Left(IMarkupPointer2 *iface, BOOL move, MARKUP_CONTEXT_TYPE *context,
2259 IHTMLElement **element, LONG *len, OLECHAR *text)
2261 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2262 FIXME("(%p)->(%x %p %p %p %p)\n", This, move, context, element, len, text);
2263 return E_NOTIMPL;
2266 static HRESULT WINAPI MarkupPointer2_Right(IMarkupPointer2 *iface, BOOL move, MARKUP_CONTEXT_TYPE *context,
2267 IHTMLElement **element, LONG *len, OLECHAR *text)
2269 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2270 FIXME("(%p)->(%x %p %p %p %p)\n", This, move, context, element, len, text);
2271 return E_NOTIMPL;
2274 static HRESULT WINAPI MarkupPointer2_CurrentScope(IMarkupPointer2 *iface, IHTMLElement **p)
2276 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2277 FIXME("(%p)->(%p)\n", This, p);
2278 return E_NOTIMPL;
2281 static HRESULT WINAPI MarkupPointer2_IsLeftOf(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2283 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2284 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2285 return E_NOTIMPL;
2288 static HRESULT WINAPI MarkupPointer2_IsLeftOfOrEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2290 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2291 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2292 return E_NOTIMPL;
2295 static HRESULT WINAPI MarkupPointer2_IsRightOf(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2297 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2298 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2299 return E_NOTIMPL;
2302 static HRESULT WINAPI MarkupPointer2_IsRightOfOrEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2304 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2305 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2306 return E_NOTIMPL;
2309 static HRESULT WINAPI MarkupPointer2_IsEqualTo(IMarkupPointer2 *iface, IMarkupPointer *that_pointer, BOOL *p)
2311 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2312 FIXME("(%p)->(%p %p)\n", This, that_pointer, p);
2313 return E_NOTIMPL;
2316 static HRESULT WINAPI MarkupPointer2_MoveUnit(IMarkupPointer2 *iface, MOVEUNIT_ACTION action)
2318 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2319 FIXME("(%p)->(%u)\n", This, action);
2320 return E_NOTIMPL;
2323 static HRESULT WINAPI MarkupPointer2_FindText(IMarkupPointer2 *iface, OLECHAR *text, DWORD flags,
2324 IMarkupPointer *end_match, IMarkupPointer *end_search)
2326 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2327 FIXME("(%p)->(%s %lx %p %p)\n", This, debugstr_w(text), flags, end_match, end_search);
2328 return E_NOTIMPL;
2331 static HRESULT WINAPI MarkupPointer2_IsAtWordBreak(IMarkupPointer2 *iface, BOOL *p)
2333 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2334 FIXME("(%p)->(%p)\n", This, p);
2335 return E_NOTIMPL;
2338 static HRESULT WINAPI MarkupPointer2_GetMarkupPosition(IMarkupPointer2 *iface, LONG *p)
2340 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2341 FIXME("(%p)->(%p)\n", This, p);
2342 return E_NOTIMPL;
2345 static HRESULT WINAPI MarkupPointer2_MoveToMarkupPosition(IMarkupPointer2 *iface, IMarkupContainer *container, LONG mp)
2347 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2348 FIXME("(%p)->(%p %ld)\n", This, container, mp);
2349 return E_NOTIMPL;
2352 static HRESULT WINAPI MarkupPointer2_MoveUnitBounded(IMarkupPointer2 *iface, MOVEUNIT_ACTION action, IMarkupPointer *boundary)
2354 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2355 FIXME("(%p)->(%u %p)\n", This, action, boundary);
2356 return E_NOTIMPL;
2359 static HRESULT WINAPI MarkupPointer2_IsInsideURL(IMarkupPointer2 *iface, IMarkupPointer *right, BOOL *p)
2361 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2362 FIXME("(%p)->(%p %p)\n", This, right, p);
2363 return E_NOTIMPL;
2366 static HRESULT WINAPI MarkupPointer2_MoveToContent(IMarkupPointer2 *iface, IHTMLElement *element, BOOL at_start)
2368 MarkupPointer *This = impl_from_IMarkupPointer2(iface);
2369 FIXME("(%p)->(%p %x)\n", This, element, at_start);
2370 return E_NOTIMPL;
2373 static const IMarkupPointer2Vtbl MarkupPointer2Vtbl = {
2374 MarkupPointer2_QueryInterface,
2375 MarkupPointer2_AddRef,
2376 MarkupPointer2_Release,
2377 MarkupPointer2_OwningDoc,
2378 MarkupPointer2_Gravity,
2379 MarkupPointer2_SetGravity,
2380 MarkupPointer2_Cling,
2381 MarkupPointer2_SetCling,
2382 MarkupPointer2_Unposition,
2383 MarkupPointer2_IsPositioned,
2384 MarkupPointer2_GetContainer,
2385 MarkupPointer2_MoveAdjacentToElement,
2386 MarkupPointer2_MoveToPointer,
2387 MarkupPointer2_MoveToContainer,
2388 MarkupPointer2_Left,
2389 MarkupPointer2_Right,
2390 MarkupPointer2_CurrentScope,
2391 MarkupPointer2_IsLeftOf,
2392 MarkupPointer2_IsLeftOfOrEqualTo,
2393 MarkupPointer2_IsRightOf,
2394 MarkupPointer2_IsRightOfOrEqualTo,
2395 MarkupPointer2_IsEqualTo,
2396 MarkupPointer2_MoveUnit,
2397 MarkupPointer2_FindText,
2398 MarkupPointer2_IsAtWordBreak,
2399 MarkupPointer2_GetMarkupPosition,
2400 MarkupPointer2_MoveToMarkupPosition,
2401 MarkupPointer2_MoveUnitBounded,
2402 MarkupPointer2_IsInsideURL,
2403 MarkupPointer2_MoveToContent
2406 HRESULT create_markup_pointer(IMarkupPointer **ret)
2408 MarkupPointer *markup_pointer;
2410 if(!(markup_pointer = malloc(sizeof(*markup_pointer))))
2411 return E_OUTOFMEMORY;
2413 markup_pointer->IMarkupPointer2_iface.lpVtbl = &MarkupPointer2Vtbl;
2414 markup_pointer->ref = 1;
2416 *ret = (IMarkupPointer*)&markup_pointer->IMarkupPointer2_iface;
2417 return S_OK;