1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * Copyright 2006-2007 Jacek Caban for CodeWeavers
3*c2c66affSColin Finck *
4*c2c66affSColin Finck * This library is free software; you can redistribute it and/or
5*c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
6*c2c66affSColin Finck * License as published by the Free Software Foundation; either
7*c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
8*c2c66affSColin Finck *
9*c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
10*c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12*c2c66affSColin Finck * Lesser General Public License for more details.
13*c2c66affSColin Finck *
14*c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
15*c2c66affSColin Finck * License along with this library; if not, write to the Free Software
16*c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17*c2c66affSColin Finck */
18*c2c66affSColin Finck
19*c2c66affSColin Finck #include "mshtml_private.h"
20*c2c66affSColin Finck
21*c2c66affSColin Finck static const WCHAR brW[] = {'b','r',0};
22*c2c66affSColin Finck static const WCHAR hrW[] = {'h','r',0};
23*c2c66affSColin Finck
24*c2c66affSColin Finck typedef struct {
25*c2c66affSColin Finck DispatchEx dispex;
26*c2c66affSColin Finck IHTMLTxtRange IHTMLTxtRange_iface;
27*c2c66affSColin Finck IOleCommandTarget IOleCommandTarget_iface;
28*c2c66affSColin Finck
29*c2c66affSColin Finck LONG ref;
30*c2c66affSColin Finck
31*c2c66affSColin Finck nsIDOMRange *nsrange;
32*c2c66affSColin Finck HTMLDocumentNode *doc;
33*c2c66affSColin Finck
34*c2c66affSColin Finck struct list entry;
35*c2c66affSColin Finck } HTMLTxtRange;
36*c2c66affSColin Finck
37*c2c66affSColin Finck typedef struct {
38*c2c66affSColin Finck WCHAR *buf;
39*c2c66affSColin Finck DWORD len;
40*c2c66affSColin Finck DWORD size;
41*c2c66affSColin Finck } wstrbuf_t;
42*c2c66affSColin Finck
43*c2c66affSColin Finck typedef struct {
44*c2c66affSColin Finck UINT16 type;
45*c2c66affSColin Finck nsIDOMNode *node;
46*c2c66affSColin Finck UINT32 off;
47*c2c66affSColin Finck } rangepoint_t;
48*c2c66affSColin Finck
49*c2c66affSColin Finck typedef enum {
50*c2c66affSColin Finck RU_UNKNOWN,
51*c2c66affSColin Finck RU_CHAR,
52*c2c66affSColin Finck RU_WORD,
53*c2c66affSColin Finck RU_SENTENCE,
54*c2c66affSColin Finck RU_TEXTEDIT
55*c2c66affSColin Finck } range_unit_t;
56*c2c66affSColin Finck
get_range_object(HTMLDocumentNode * doc,IHTMLTxtRange * iface)57*c2c66affSColin Finck static HTMLTxtRange *get_range_object(HTMLDocumentNode *doc, IHTMLTxtRange *iface)
58*c2c66affSColin Finck {
59*c2c66affSColin Finck HTMLTxtRange *iter;
60*c2c66affSColin Finck
61*c2c66affSColin Finck LIST_FOR_EACH_ENTRY(iter, &doc->range_list, HTMLTxtRange, entry) {
62*c2c66affSColin Finck if(&iter->IHTMLTxtRange_iface == iface)
63*c2c66affSColin Finck return iter;
64*c2c66affSColin Finck }
65*c2c66affSColin Finck
66*c2c66affSColin Finck ERR("Could not find range in document\n");
67*c2c66affSColin Finck return NULL;
68*c2c66affSColin Finck }
69*c2c66affSColin Finck
string_to_unit(LPCWSTR str)70*c2c66affSColin Finck static range_unit_t string_to_unit(LPCWSTR str)
71*c2c66affSColin Finck {
72*c2c66affSColin Finck static const WCHAR characterW[] =
73*c2c66affSColin Finck {'c','h','a','r','a','c','t','e','r',0};
74*c2c66affSColin Finck static const WCHAR wordW[] =
75*c2c66affSColin Finck {'w','o','r','d',0};
76*c2c66affSColin Finck static const WCHAR sentenceW[] =
77*c2c66affSColin Finck {'s','e','n','t','e','n','c','e',0};
78*c2c66affSColin Finck static const WCHAR texteditW[] =
79*c2c66affSColin Finck {'t','e','x','t','e','d','i','t',0};
80*c2c66affSColin Finck
81*c2c66affSColin Finck if(!strcmpiW(str, characterW)) return RU_CHAR;
82*c2c66affSColin Finck if(!strcmpiW(str, wordW)) return RU_WORD;
83*c2c66affSColin Finck if(!strcmpiW(str, sentenceW)) return RU_SENTENCE;
84*c2c66affSColin Finck if(!strcmpiW(str, texteditW)) return RU_TEXTEDIT;
85*c2c66affSColin Finck
86*c2c66affSColin Finck return RU_UNKNOWN;
87*c2c66affSColin Finck }
88*c2c66affSColin Finck
string_to_nscmptype(LPCWSTR str)89*c2c66affSColin Finck static int string_to_nscmptype(LPCWSTR str)
90*c2c66affSColin Finck {
91*c2c66affSColin Finck static const WCHAR seW[] = {'S','t','a','r','t','T','o','E','n','d',0};
92*c2c66affSColin Finck static const WCHAR ssW[] = {'S','t','a','r','t','T','o','S','t','a','r','t',0};
93*c2c66affSColin Finck static const WCHAR esW[] = {'E','n','d','T','o','S','t','a','r','t',0};
94*c2c66affSColin Finck static const WCHAR eeW[] = {'E','n','d','T','o','E','n','d',0};
95*c2c66affSColin Finck
96*c2c66affSColin Finck if(!strcmpiW(str, seW)) return NS_START_TO_END;
97*c2c66affSColin Finck if(!strcmpiW(str, ssW)) return NS_START_TO_START;
98*c2c66affSColin Finck if(!strcmpiW(str, esW)) return NS_END_TO_START;
99*c2c66affSColin Finck if(!strcmpiW(str, eeW)) return NS_END_TO_END;
100*c2c66affSColin Finck
101*c2c66affSColin Finck return -1;
102*c2c66affSColin Finck }
103*c2c66affSColin Finck
get_node_type(nsIDOMNode * node)104*c2c66affSColin Finck static UINT16 get_node_type(nsIDOMNode *node)
105*c2c66affSColin Finck {
106*c2c66affSColin Finck UINT16 type = 0;
107*c2c66affSColin Finck
108*c2c66affSColin Finck if(node)
109*c2c66affSColin Finck nsIDOMNode_GetNodeType(node, &type);
110*c2c66affSColin Finck
111*c2c66affSColin Finck return type;
112*c2c66affSColin Finck }
113*c2c66affSColin Finck
get_text_node_data(nsIDOMNode * node,nsAString * nsstr,const PRUnichar ** str)114*c2c66affSColin Finck static void get_text_node_data(nsIDOMNode *node, nsAString *nsstr, const PRUnichar **str)
115*c2c66affSColin Finck {
116*c2c66affSColin Finck nsIDOMText *nstext;
117*c2c66affSColin Finck nsresult nsres;
118*c2c66affSColin Finck
119*c2c66affSColin Finck nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
120*c2c66affSColin Finck assert(nsres == NS_OK);
121*c2c66affSColin Finck
122*c2c66affSColin Finck nsAString_Init(nsstr, NULL);
123*c2c66affSColin Finck nsres = nsIDOMText_GetData(nstext, nsstr);
124*c2c66affSColin Finck nsIDOMText_Release(nstext);
125*c2c66affSColin Finck if(NS_FAILED(nsres))
126*c2c66affSColin Finck ERR("GetData failed: %08x\n", nsres);
127*c2c66affSColin Finck
128*c2c66affSColin Finck nsAString_GetData(nsstr, str);
129*c2c66affSColin Finck }
130*c2c66affSColin Finck
get_child_node(nsIDOMNode * node,UINT32 off)131*c2c66affSColin Finck static nsIDOMNode *get_child_node(nsIDOMNode *node, UINT32 off)
132*c2c66affSColin Finck {
133*c2c66affSColin Finck nsIDOMNodeList *node_list;
134*c2c66affSColin Finck nsIDOMNode *ret = NULL;
135*c2c66affSColin Finck
136*c2c66affSColin Finck nsIDOMNode_GetChildNodes(node, &node_list);
137*c2c66affSColin Finck nsIDOMNodeList_Item(node_list, off, &ret);
138*c2c66affSColin Finck nsIDOMNodeList_Release(node_list);
139*c2c66affSColin Finck
140*c2c66affSColin Finck return ret;
141*c2c66affSColin Finck }
142*c2c66affSColin Finck
143*c2c66affSColin Finck /* This is very inefficient, but there is no faster way to compute index in
144*c2c66affSColin Finck * child node list using public API. Gecko has internal nsINode::IndexOf
145*c2c66affSColin Finck * function that we could consider exporting and use instead. */
get_child_index(nsIDOMNode * parent,nsIDOMNode * child)146*c2c66affSColin Finck static int get_child_index(nsIDOMNode *parent, nsIDOMNode *child)
147*c2c66affSColin Finck {
148*c2c66affSColin Finck nsIDOMNodeList *node_list;
149*c2c66affSColin Finck nsIDOMNode *node;
150*c2c66affSColin Finck int ret = 0;
151*c2c66affSColin Finck nsresult nsres;
152*c2c66affSColin Finck
153*c2c66affSColin Finck nsres = nsIDOMNode_GetChildNodes(parent, &node_list);
154*c2c66affSColin Finck assert(nsres == NS_OK);
155*c2c66affSColin Finck
156*c2c66affSColin Finck while(1) {
157*c2c66affSColin Finck nsres = nsIDOMNodeList_Item(node_list, ret, &node);
158*c2c66affSColin Finck assert(nsres == NS_OK && node);
159*c2c66affSColin Finck if(node == child) {
160*c2c66affSColin Finck nsIDOMNode_Release(node);
161*c2c66affSColin Finck break;
162*c2c66affSColin Finck }
163*c2c66affSColin Finck nsIDOMNode_Release(node);
164*c2c66affSColin Finck ret++;
165*c2c66affSColin Finck }
166*c2c66affSColin Finck
167*c2c66affSColin Finck nsIDOMNodeList_Release(node_list);
168*c2c66affSColin Finck return ret;
169*c2c66affSColin Finck }
170*c2c66affSColin Finck
init_rangepoint(rangepoint_t * rangepoint,nsIDOMNode * node,UINT32 off)171*c2c66affSColin Finck static void init_rangepoint(rangepoint_t *rangepoint, nsIDOMNode *node, UINT32 off)
172*c2c66affSColin Finck {
173*c2c66affSColin Finck nsIDOMNode_AddRef(node);
174*c2c66affSColin Finck
175*c2c66affSColin Finck rangepoint->type = get_node_type(node);
176*c2c66affSColin Finck rangepoint->node = node;
177*c2c66affSColin Finck rangepoint->off = off;
178*c2c66affSColin Finck }
179*c2c66affSColin Finck
free_rangepoint(rangepoint_t * rangepoint)180*c2c66affSColin Finck static inline void free_rangepoint(rangepoint_t *rangepoint)
181*c2c66affSColin Finck {
182*c2c66affSColin Finck nsIDOMNode_Release(rangepoint->node);
183*c2c66affSColin Finck }
184*c2c66affSColin Finck
rangepoint_cmp(const rangepoint_t * point1,const rangepoint_t * point2)185*c2c66affSColin Finck static inline BOOL rangepoint_cmp(const rangepoint_t *point1, const rangepoint_t *point2)
186*c2c66affSColin Finck {
187*c2c66affSColin Finck return point1->node == point2->node && point1->off == point2->off;
188*c2c66affSColin Finck }
189*c2c66affSColin Finck
rangepoint_next_node(rangepoint_t * iter)190*c2c66affSColin Finck static BOOL rangepoint_next_node(rangepoint_t *iter)
191*c2c66affSColin Finck {
192*c2c66affSColin Finck nsIDOMNode *node;
193*c2c66affSColin Finck UINT32 off;
194*c2c66affSColin Finck nsresult nsres;
195*c2c66affSColin Finck
196*c2c66affSColin Finck /* Try to move to the child node. */
197*c2c66affSColin Finck node = get_child_node(iter->node, iter->off);
198*c2c66affSColin Finck if(node) {
199*c2c66affSColin Finck free_rangepoint(iter);
200*c2c66affSColin Finck init_rangepoint(iter, node, 0);
201*c2c66affSColin Finck nsIDOMNode_Release(node);
202*c2c66affSColin Finck return TRUE;
203*c2c66affSColin Finck }
204*c2c66affSColin Finck
205*c2c66affSColin Finck /* There are no more children in the node. Move to parent. */
206*c2c66affSColin Finck nsres = nsIDOMNode_GetParentNode(iter->node, &node);
207*c2c66affSColin Finck assert(nsres == NS_OK);
208*c2c66affSColin Finck if(!node)
209*c2c66affSColin Finck return FALSE;
210*c2c66affSColin Finck
211*c2c66affSColin Finck off = get_child_index(node, iter->node)+1;
212*c2c66affSColin Finck free_rangepoint(iter);
213*c2c66affSColin Finck init_rangepoint(iter, node, off);
214*c2c66affSColin Finck nsIDOMNode_Release(node);
215*c2c66affSColin Finck return TRUE;
216*c2c66affSColin Finck }
217*c2c66affSColin Finck
get_child_count(nsIDOMNode * node)218*c2c66affSColin Finck static UINT32 get_child_count(nsIDOMNode *node)
219*c2c66affSColin Finck {
220*c2c66affSColin Finck nsIDOMNodeList *node_list;
221*c2c66affSColin Finck UINT32 ret;
222*c2c66affSColin Finck nsresult nsres;
223*c2c66affSColin Finck
224*c2c66affSColin Finck nsres = nsIDOMNode_GetChildNodes(node, &node_list);
225*c2c66affSColin Finck assert(nsres == NS_OK);
226*c2c66affSColin Finck
227*c2c66affSColin Finck nsres = nsIDOMNodeList_GetLength(node_list, &ret);
228*c2c66affSColin Finck nsIDOMNodeList_Release(node_list);
229*c2c66affSColin Finck assert(nsres == NS_OK);
230*c2c66affSColin Finck
231*c2c66affSColin Finck return ret;
232*c2c66affSColin Finck }
233*c2c66affSColin Finck
get_text_length(nsIDOMNode * node)234*c2c66affSColin Finck static UINT32 get_text_length(nsIDOMNode *node)
235*c2c66affSColin Finck {
236*c2c66affSColin Finck nsIDOMText *nstext;
237*c2c66affSColin Finck UINT32 ret;
238*c2c66affSColin Finck nsresult nsres;
239*c2c66affSColin Finck
240*c2c66affSColin Finck nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
241*c2c66affSColin Finck assert(nsres == NS_OK);
242*c2c66affSColin Finck
243*c2c66affSColin Finck nsres = nsIDOMText_GetLength(nstext, &ret);
244*c2c66affSColin Finck nsIDOMText_Release(nstext);
245*c2c66affSColin Finck assert(nsres == NS_OK);
246*c2c66affSColin Finck
247*c2c66affSColin Finck return ret;
248*c2c66affSColin Finck }
249*c2c66affSColin Finck
rangepoint_prev_node(rangepoint_t * iter)250*c2c66affSColin Finck static BOOL rangepoint_prev_node(rangepoint_t *iter)
251*c2c66affSColin Finck {
252*c2c66affSColin Finck nsIDOMNode *node;
253*c2c66affSColin Finck UINT32 off;
254*c2c66affSColin Finck nsresult nsres;
255*c2c66affSColin Finck
256*c2c66affSColin Finck /* Try to move to the child node. */
257*c2c66affSColin Finck if(iter->off) {
258*c2c66affSColin Finck node = get_child_node(iter->node, iter->off-1);
259*c2c66affSColin Finck assert(node != NULL);
260*c2c66affSColin Finck
261*c2c66affSColin Finck off = get_node_type(node) == TEXT_NODE ? get_text_length(node) : get_child_count(node);
262*c2c66affSColin Finck free_rangepoint(iter);
263*c2c66affSColin Finck init_rangepoint(iter, node, off);
264*c2c66affSColin Finck nsIDOMNode_Release(node);
265*c2c66affSColin Finck return TRUE;
266*c2c66affSColin Finck }
267*c2c66affSColin Finck
268*c2c66affSColin Finck /* There are no more children in the node. Move to parent. */
269*c2c66affSColin Finck nsres = nsIDOMNode_GetParentNode(iter->node, &node);
270*c2c66affSColin Finck assert(nsres == NS_OK);
271*c2c66affSColin Finck if(!node)
272*c2c66affSColin Finck return FALSE;
273*c2c66affSColin Finck
274*c2c66affSColin Finck off = get_child_index(node, iter->node);
275*c2c66affSColin Finck free_rangepoint(iter);
276*c2c66affSColin Finck init_rangepoint(iter, node, off);
277*c2c66affSColin Finck return TRUE;
278*c2c66affSColin Finck }
279*c2c66affSColin Finck
get_start_point(HTMLTxtRange * This,rangepoint_t * ret)280*c2c66affSColin Finck static void get_start_point(HTMLTxtRange *This, rangepoint_t *ret)
281*c2c66affSColin Finck {
282*c2c66affSColin Finck nsIDOMNode *node;
283*c2c66affSColin Finck LONG off;
284*c2c66affSColin Finck
285*c2c66affSColin Finck nsIDOMRange_GetStartContainer(This->nsrange, &node);
286*c2c66affSColin Finck nsIDOMRange_GetStartOffset(This->nsrange, &off);
287*c2c66affSColin Finck
288*c2c66affSColin Finck init_rangepoint(ret, node, off);
289*c2c66affSColin Finck
290*c2c66affSColin Finck nsIDOMNode_Release(node);
291*c2c66affSColin Finck }
292*c2c66affSColin Finck
get_end_point(HTMLTxtRange * This,rangepoint_t * ret)293*c2c66affSColin Finck static void get_end_point(HTMLTxtRange *This, rangepoint_t *ret)
294*c2c66affSColin Finck {
295*c2c66affSColin Finck nsIDOMNode *node;
296*c2c66affSColin Finck LONG off;
297*c2c66affSColin Finck
298*c2c66affSColin Finck nsIDOMRange_GetEndContainer(This->nsrange, &node);
299*c2c66affSColin Finck nsIDOMRange_GetEndOffset(This->nsrange, &off);
300*c2c66affSColin Finck
301*c2c66affSColin Finck init_rangepoint(ret, node, off);
302*c2c66affSColin Finck
303*c2c66affSColin Finck nsIDOMNode_Release(node);
304*c2c66affSColin Finck }
305*c2c66affSColin Finck
set_start_point(HTMLTxtRange * This,const rangepoint_t * start)306*c2c66affSColin Finck static void set_start_point(HTMLTxtRange *This, const rangepoint_t *start)
307*c2c66affSColin Finck {
308*c2c66affSColin Finck nsresult nsres = nsIDOMRange_SetStart(This->nsrange, start->node, start->off);
309*c2c66affSColin Finck if(NS_FAILED(nsres))
310*c2c66affSColin Finck ERR("failed: %08x\n", nsres);
311*c2c66affSColin Finck }
312*c2c66affSColin Finck
set_end_point(HTMLTxtRange * This,const rangepoint_t * end)313*c2c66affSColin Finck static void set_end_point(HTMLTxtRange *This, const rangepoint_t *end)
314*c2c66affSColin Finck {
315*c2c66affSColin Finck nsresult nsres = nsIDOMRange_SetEnd(This->nsrange, end->node, end->off);
316*c2c66affSColin Finck if(NS_FAILED(nsres))
317*c2c66affSColin Finck ERR("failed: %08x\n", nsres);
318*c2c66affSColin Finck }
319*c2c66affSColin Finck
is_elem_tag(nsIDOMNode * node,LPCWSTR istag)320*c2c66affSColin Finck static BOOL is_elem_tag(nsIDOMNode *node, LPCWSTR istag)
321*c2c66affSColin Finck {
322*c2c66affSColin Finck nsIDOMElement *elem;
323*c2c66affSColin Finck nsAString tag_str;
324*c2c66affSColin Finck const PRUnichar *tag;
325*c2c66affSColin Finck BOOL ret = FALSE;
326*c2c66affSColin Finck nsresult nsres;
327*c2c66affSColin Finck
328*c2c66affSColin Finck nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMElement, (void**)&elem);
329*c2c66affSColin Finck if(NS_FAILED(nsres))
330*c2c66affSColin Finck return FALSE;
331*c2c66affSColin Finck
332*c2c66affSColin Finck nsAString_Init(&tag_str, NULL);
333*c2c66affSColin Finck nsIDOMElement_GetTagName(elem, &tag_str);
334*c2c66affSColin Finck nsIDOMElement_Release(elem);
335*c2c66affSColin Finck nsAString_GetData(&tag_str, &tag);
336*c2c66affSColin Finck
337*c2c66affSColin Finck ret = !strcmpiW(tag, istag);
338*c2c66affSColin Finck
339*c2c66affSColin Finck nsAString_Finish(&tag_str);
340*c2c66affSColin Finck
341*c2c66affSColin Finck return ret;
342*c2c66affSColin Finck }
343*c2c66affSColin Finck
wstrbuf_init(wstrbuf_t * buf)344*c2c66affSColin Finck static inline BOOL wstrbuf_init(wstrbuf_t *buf)
345*c2c66affSColin Finck {
346*c2c66affSColin Finck buf->len = 0;
347*c2c66affSColin Finck buf->size = 16;
348*c2c66affSColin Finck buf->buf = heap_alloc(buf->size * sizeof(WCHAR));
349*c2c66affSColin Finck if (!buf->buf) return FALSE;
350*c2c66affSColin Finck *buf->buf = 0;
351*c2c66affSColin Finck return TRUE;
352*c2c66affSColin Finck }
353*c2c66affSColin Finck
wstrbuf_finish(wstrbuf_t * buf)354*c2c66affSColin Finck static inline void wstrbuf_finish(wstrbuf_t *buf)
355*c2c66affSColin Finck {
356*c2c66affSColin Finck heap_free(buf->buf);
357*c2c66affSColin Finck }
358*c2c66affSColin Finck
wstrbuf_append_len(wstrbuf_t * buf,LPCWSTR str,int len)359*c2c66affSColin Finck static void wstrbuf_append_len(wstrbuf_t *buf, LPCWSTR str, int len)
360*c2c66affSColin Finck {
361*c2c66affSColin Finck if(buf->len+len >= buf->size) {
362*c2c66affSColin Finck buf->size = 2*buf->size+len;
363*c2c66affSColin Finck buf->buf = heap_realloc(buf->buf, buf->size * sizeof(WCHAR));
364*c2c66affSColin Finck }
365*c2c66affSColin Finck
366*c2c66affSColin Finck memcpy(buf->buf+buf->len, str, len*sizeof(WCHAR));
367*c2c66affSColin Finck buf->len += len;
368*c2c66affSColin Finck buf->buf[buf->len] = 0;
369*c2c66affSColin Finck }
370*c2c66affSColin Finck
wstrbuf_append_nodetxt(wstrbuf_t * buf,LPCWSTR str,int len)371*c2c66affSColin Finck static void wstrbuf_append_nodetxt(wstrbuf_t *buf, LPCWSTR str, int len)
372*c2c66affSColin Finck {
373*c2c66affSColin Finck const WCHAR *s = str;
374*c2c66affSColin Finck WCHAR *d;
375*c2c66affSColin Finck
376*c2c66affSColin Finck TRACE("%s\n", debugstr_wn(str, len));
377*c2c66affSColin Finck
378*c2c66affSColin Finck if(buf->len+len >= buf->size) {
379*c2c66affSColin Finck buf->size = 2*buf->size+len;
380*c2c66affSColin Finck buf->buf = heap_realloc(buf->buf, buf->size * sizeof(WCHAR));
381*c2c66affSColin Finck }
382*c2c66affSColin Finck
383*c2c66affSColin Finck if(buf->len && isspaceW(buf->buf[buf->len-1])) {
384*c2c66affSColin Finck while(s < str+len && isspaceW(*s))
385*c2c66affSColin Finck s++;
386*c2c66affSColin Finck }
387*c2c66affSColin Finck
388*c2c66affSColin Finck d = buf->buf+buf->len;
389*c2c66affSColin Finck while(s < str+len) {
390*c2c66affSColin Finck if(isspaceW(*s)) {
391*c2c66affSColin Finck *d++ = ' ';
392*c2c66affSColin Finck s++;
393*c2c66affSColin Finck while(s < str+len && isspaceW(*s))
394*c2c66affSColin Finck s++;
395*c2c66affSColin Finck }else {
396*c2c66affSColin Finck *d++ = *s++;
397*c2c66affSColin Finck }
398*c2c66affSColin Finck }
399*c2c66affSColin Finck
400*c2c66affSColin Finck buf->len = d - buf->buf;
401*c2c66affSColin Finck *d = 0;
402*c2c66affSColin Finck }
403*c2c66affSColin Finck
wstrbuf_append_node(wstrbuf_t * buf,nsIDOMNode * node,BOOL ignore_text)404*c2c66affSColin Finck static void wstrbuf_append_node(wstrbuf_t *buf, nsIDOMNode *node, BOOL ignore_text)
405*c2c66affSColin Finck {
406*c2c66affSColin Finck
407*c2c66affSColin Finck switch(get_node_type(node)) {
408*c2c66affSColin Finck case TEXT_NODE: {
409*c2c66affSColin Finck nsIDOMText *nstext;
410*c2c66affSColin Finck nsAString data_str;
411*c2c66affSColin Finck const PRUnichar *data;
412*c2c66affSColin Finck
413*c2c66affSColin Finck if(ignore_text)
414*c2c66affSColin Finck break;
415*c2c66affSColin Finck
416*c2c66affSColin Finck nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
417*c2c66affSColin Finck
418*c2c66affSColin Finck nsAString_Init(&data_str, NULL);
419*c2c66affSColin Finck nsIDOMText_GetData(nstext, &data_str);
420*c2c66affSColin Finck nsAString_GetData(&data_str, &data);
421*c2c66affSColin Finck wstrbuf_append_nodetxt(buf, data, strlenW(data));
422*c2c66affSColin Finck nsAString_Finish(&data_str);
423*c2c66affSColin Finck
424*c2c66affSColin Finck nsIDOMText_Release(nstext);
425*c2c66affSColin Finck
426*c2c66affSColin Finck break;
427*c2c66affSColin Finck }
428*c2c66affSColin Finck case ELEMENT_NODE:
429*c2c66affSColin Finck if(is_elem_tag(node, brW)) {
430*c2c66affSColin Finck static const WCHAR endlW[] = {'\r','\n'};
431*c2c66affSColin Finck wstrbuf_append_len(buf, endlW, 2);
432*c2c66affSColin Finck }else if(is_elem_tag(node, hrW)) {
433*c2c66affSColin Finck static const WCHAR endl2W[] = {'\r','\n','\r','\n'};
434*c2c66affSColin Finck wstrbuf_append_len(buf, endl2W, 4);
435*c2c66affSColin Finck }
436*c2c66affSColin Finck }
437*c2c66affSColin Finck }
438*c2c66affSColin Finck
wstrbuf_append_node_rec(wstrbuf_t * buf,nsIDOMNode * node)439*c2c66affSColin Finck static void wstrbuf_append_node_rec(wstrbuf_t *buf, nsIDOMNode *node)
440*c2c66affSColin Finck {
441*c2c66affSColin Finck nsIDOMNode *iter, *tmp;
442*c2c66affSColin Finck
443*c2c66affSColin Finck wstrbuf_append_node(buf, node, FALSE);
444*c2c66affSColin Finck
445*c2c66affSColin Finck nsIDOMNode_GetFirstChild(node, &iter);
446*c2c66affSColin Finck while(iter) {
447*c2c66affSColin Finck wstrbuf_append_node_rec(buf, iter);
448*c2c66affSColin Finck nsIDOMNode_GetNextSibling(iter, &tmp);
449*c2c66affSColin Finck nsIDOMNode_Release(iter);
450*c2c66affSColin Finck iter = tmp;
451*c2c66affSColin Finck }
452*c2c66affSColin Finck }
453*c2c66affSColin Finck
range_to_string(HTMLTxtRange * This,wstrbuf_t * buf)454*c2c66affSColin Finck static void range_to_string(HTMLTxtRange *This, wstrbuf_t *buf)
455*c2c66affSColin Finck {
456*c2c66affSColin Finck rangepoint_t end_pos, iter;
457*c2c66affSColin Finck cpp_bool collapsed;
458*c2c66affSColin Finck
459*c2c66affSColin Finck nsIDOMRange_GetCollapsed(This->nsrange, &collapsed);
460*c2c66affSColin Finck if(collapsed) {
461*c2c66affSColin Finck wstrbuf_finish(buf);
462*c2c66affSColin Finck buf->buf = NULL;
463*c2c66affSColin Finck buf->size = 0;
464*c2c66affSColin Finck return;
465*c2c66affSColin Finck }
466*c2c66affSColin Finck
467*c2c66affSColin Finck get_end_point(This, &end_pos);
468*c2c66affSColin Finck get_start_point(This, &iter);
469*c2c66affSColin Finck
470*c2c66affSColin Finck do {
471*c2c66affSColin Finck if(iter.type == TEXT_NODE) {
472*c2c66affSColin Finck const PRUnichar *str;
473*c2c66affSColin Finck nsAString nsstr;
474*c2c66affSColin Finck
475*c2c66affSColin Finck get_text_node_data(iter.node, &nsstr, &str);
476*c2c66affSColin Finck
477*c2c66affSColin Finck if(iter.node == end_pos.node) {
478*c2c66affSColin Finck wstrbuf_append_nodetxt(buf, str+iter.off, end_pos.off-iter.off);
479*c2c66affSColin Finck nsAString_Finish(&nsstr);
480*c2c66affSColin Finck break;
481*c2c66affSColin Finck }
482*c2c66affSColin Finck
483*c2c66affSColin Finck wstrbuf_append_nodetxt(buf, str+iter.off, strlenW(str+iter.off));
484*c2c66affSColin Finck nsAString_Finish(&nsstr);
485*c2c66affSColin Finck }else {
486*c2c66affSColin Finck nsIDOMNode *node;
487*c2c66affSColin Finck
488*c2c66affSColin Finck node = get_child_node(iter.node, iter.off);
489*c2c66affSColin Finck if(node) {
490*c2c66affSColin Finck wstrbuf_append_node(buf, node, TRUE);
491*c2c66affSColin Finck nsIDOMNode_Release(node);
492*c2c66affSColin Finck }
493*c2c66affSColin Finck }
494*c2c66affSColin Finck
495*c2c66affSColin Finck if(!rangepoint_next_node(&iter)) {
496*c2c66affSColin Finck ERR("End of document?\n");
497*c2c66affSColin Finck break;
498*c2c66affSColin Finck }
499*c2c66affSColin Finck }while(!rangepoint_cmp(&iter, &end_pos));
500*c2c66affSColin Finck
501*c2c66affSColin Finck free_rangepoint(&iter);
502*c2c66affSColin Finck free_rangepoint(&end_pos);
503*c2c66affSColin Finck
504*c2c66affSColin Finck if(buf->len) {
505*c2c66affSColin Finck WCHAR *p;
506*c2c66affSColin Finck
507*c2c66affSColin Finck for(p = buf->buf+buf->len-1; p >= buf->buf && isspaceW(*p); p--);
508*c2c66affSColin Finck
509*c2c66affSColin Finck p = strchrW(p, '\r');
510*c2c66affSColin Finck if(p)
511*c2c66affSColin Finck *p = 0;
512*c2c66affSColin Finck }
513*c2c66affSColin Finck }
514*c2c66affSColin Finck
get_node_text(HTMLDOMNode * node,BSTR * ret)515*c2c66affSColin Finck HRESULT get_node_text(HTMLDOMNode *node, BSTR *ret)
516*c2c66affSColin Finck {
517*c2c66affSColin Finck wstrbuf_t buf;
518*c2c66affSColin Finck HRESULT hres = S_OK;
519*c2c66affSColin Finck
520*c2c66affSColin Finck if (!wstrbuf_init(&buf))
521*c2c66affSColin Finck return E_OUTOFMEMORY;
522*c2c66affSColin Finck wstrbuf_append_node_rec(&buf, node->nsnode);
523*c2c66affSColin Finck if(buf.buf) {
524*c2c66affSColin Finck *ret = SysAllocString(buf.buf);
525*c2c66affSColin Finck if(!*ret)
526*c2c66affSColin Finck hres = E_OUTOFMEMORY;
527*c2c66affSColin Finck } else {
528*c2c66affSColin Finck *ret = NULL;
529*c2c66affSColin Finck }
530*c2c66affSColin Finck wstrbuf_finish(&buf);
531*c2c66affSColin Finck
532*c2c66affSColin Finck if(SUCCEEDED(hres))
533*c2c66affSColin Finck TRACE("ret %s\n", debugstr_w(*ret));
534*c2c66affSColin Finck return hres;
535*c2c66affSColin Finck }
536*c2c66affSColin Finck
move_next_char(rangepoint_t * iter)537*c2c66affSColin Finck static WCHAR move_next_char(rangepoint_t *iter)
538*c2c66affSColin Finck {
539*c2c66affSColin Finck rangepoint_t last_space;
540*c2c66affSColin Finck nsIDOMNode *node;
541*c2c66affSColin Finck WCHAR cspace = 0;
542*c2c66affSColin Finck const WCHAR *p;
543*c2c66affSColin Finck
544*c2c66affSColin Finck do {
545*c2c66affSColin Finck switch(iter->type) {
546*c2c66affSColin Finck case TEXT_NODE: {
547*c2c66affSColin Finck const PRUnichar *str;
548*c2c66affSColin Finck nsAString nsstr;
549*c2c66affSColin Finck WCHAR c;
550*c2c66affSColin Finck
551*c2c66affSColin Finck get_text_node_data(iter->node, &nsstr, &str);
552*c2c66affSColin Finck p = str+iter->off;
553*c2c66affSColin Finck if(!*p) {
554*c2c66affSColin Finck nsAString_Finish(&nsstr);
555*c2c66affSColin Finck break;
556*c2c66affSColin Finck }
557*c2c66affSColin Finck
558*c2c66affSColin Finck c = *p;
559*c2c66affSColin Finck if(isspaceW(c)) {
560*c2c66affSColin Finck while(isspaceW(*p))
561*c2c66affSColin Finck p++;
562*c2c66affSColin Finck
563*c2c66affSColin Finck if(cspace)
564*c2c66affSColin Finck free_rangepoint(&last_space);
565*c2c66affSColin Finck else
566*c2c66affSColin Finck cspace = ' ';
567*c2c66affSColin Finck
568*c2c66affSColin Finck iter->off = p-str;
569*c2c66affSColin Finck c = *p;
570*c2c66affSColin Finck nsAString_Finish(&nsstr);
571*c2c66affSColin Finck if(!c) { /* continue to skip spaces */
572*c2c66affSColin Finck init_rangepoint(&last_space, iter->node, iter->off);
573*c2c66affSColin Finck break;
574*c2c66affSColin Finck }
575*c2c66affSColin Finck
576*c2c66affSColin Finck return cspace;
577*c2c66affSColin Finck }else {
578*c2c66affSColin Finck nsAString_Finish(&nsstr);
579*c2c66affSColin Finck }
580*c2c66affSColin Finck
581*c2c66affSColin Finck /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
582*c2c66affSColin Finck if(cspace) {
583*c2c66affSColin Finck free_rangepoint(iter);
584*c2c66affSColin Finck *iter = last_space;
585*c2c66affSColin Finck return cspace;
586*c2c66affSColin Finck }
587*c2c66affSColin Finck
588*c2c66affSColin Finck iter->off++;
589*c2c66affSColin Finck return c;
590*c2c66affSColin Finck }
591*c2c66affSColin Finck case ELEMENT_NODE:
592*c2c66affSColin Finck node = get_child_node(iter->node, iter->off);
593*c2c66affSColin Finck if(!node)
594*c2c66affSColin Finck break;
595*c2c66affSColin Finck
596*c2c66affSColin Finck if(is_elem_tag(node, brW)) {
597*c2c66affSColin Finck if(cspace) {
598*c2c66affSColin Finck nsIDOMNode_Release(node);
599*c2c66affSColin Finck free_rangepoint(iter);
600*c2c66affSColin Finck *iter = last_space;
601*c2c66affSColin Finck return cspace;
602*c2c66affSColin Finck }
603*c2c66affSColin Finck
604*c2c66affSColin Finck cspace = '\n';
605*c2c66affSColin Finck init_rangepoint(&last_space, iter->node, iter->off+1);
606*c2c66affSColin Finck }else if(is_elem_tag(node, hrW)) {
607*c2c66affSColin Finck nsIDOMNode_Release(node);
608*c2c66affSColin Finck if(cspace) {
609*c2c66affSColin Finck free_rangepoint(iter);
610*c2c66affSColin Finck *iter = last_space;
611*c2c66affSColin Finck return cspace;
612*c2c66affSColin Finck }
613*c2c66affSColin Finck
614*c2c66affSColin Finck iter->off++;
615*c2c66affSColin Finck return '\n';
616*c2c66affSColin Finck }
617*c2c66affSColin Finck
618*c2c66affSColin Finck nsIDOMNode_Release(node);
619*c2c66affSColin Finck }
620*c2c66affSColin Finck }while(rangepoint_next_node(iter));
621*c2c66affSColin Finck
622*c2c66affSColin Finck return cspace;
623*c2c66affSColin Finck }
624*c2c66affSColin Finck
move_prev_char(rangepoint_t * iter)625*c2c66affSColin Finck static WCHAR move_prev_char(rangepoint_t *iter)
626*c2c66affSColin Finck {
627*c2c66affSColin Finck rangepoint_t last_space;
628*c2c66affSColin Finck nsIDOMNode *node;
629*c2c66affSColin Finck WCHAR cspace = 0;
630*c2c66affSColin Finck const WCHAR *p;
631*c2c66affSColin Finck
632*c2c66affSColin Finck do {
633*c2c66affSColin Finck switch(iter->type) {
634*c2c66affSColin Finck case TEXT_NODE: {
635*c2c66affSColin Finck const PRUnichar *str;
636*c2c66affSColin Finck nsAString nsstr;
637*c2c66affSColin Finck WCHAR c;
638*c2c66affSColin Finck
639*c2c66affSColin Finck if(!iter->off)
640*c2c66affSColin Finck break;
641*c2c66affSColin Finck
642*c2c66affSColin Finck get_text_node_data(iter->node, &nsstr, &str);
643*c2c66affSColin Finck
644*c2c66affSColin Finck p = str+iter->off-1;
645*c2c66affSColin Finck c = *p;
646*c2c66affSColin Finck
647*c2c66affSColin Finck if(isspaceW(c)) {
648*c2c66affSColin Finck while(p > str && isspaceW(*(p-1)))
649*c2c66affSColin Finck p--;
650*c2c66affSColin Finck
651*c2c66affSColin Finck if(cspace)
652*c2c66affSColin Finck free_rangepoint(&last_space);
653*c2c66affSColin Finck else
654*c2c66affSColin Finck cspace = ' ';
655*c2c66affSColin Finck
656*c2c66affSColin Finck iter->off = p-str;
657*c2c66affSColin Finck nsAString_Finish(&nsstr);
658*c2c66affSColin Finck if(p == str) { /* continue to skip spaces */
659*c2c66affSColin Finck init_rangepoint(&last_space, iter->node, iter->off);
660*c2c66affSColin Finck break;
661*c2c66affSColin Finck }
662*c2c66affSColin Finck
663*c2c66affSColin Finck return cspace;
664*c2c66affSColin Finck }else {
665*c2c66affSColin Finck nsAString_Finish(&nsstr);
666*c2c66affSColin Finck }
667*c2c66affSColin Finck
668*c2c66affSColin Finck /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
669*c2c66affSColin Finck if(cspace) {
670*c2c66affSColin Finck free_rangepoint(iter);
671*c2c66affSColin Finck *iter = last_space;
672*c2c66affSColin Finck return cspace;
673*c2c66affSColin Finck }
674*c2c66affSColin Finck
675*c2c66affSColin Finck iter->off--;
676*c2c66affSColin Finck return c;
677*c2c66affSColin Finck }
678*c2c66affSColin Finck case ELEMENT_NODE:
679*c2c66affSColin Finck if(!iter->off)
680*c2c66affSColin Finck break;
681*c2c66affSColin Finck
682*c2c66affSColin Finck node = get_child_node(iter->node, iter->off-1);
683*c2c66affSColin Finck if(!node)
684*c2c66affSColin Finck break;
685*c2c66affSColin Finck
686*c2c66affSColin Finck if(is_elem_tag(node, brW)) {
687*c2c66affSColin Finck if(cspace)
688*c2c66affSColin Finck free_rangepoint(&last_space);
689*c2c66affSColin Finck cspace = '\n';
690*c2c66affSColin Finck init_rangepoint(&last_space, iter->node, iter->off-1);
691*c2c66affSColin Finck }else if(is_elem_tag(node, hrW)) {
692*c2c66affSColin Finck nsIDOMNode_Release(node);
693*c2c66affSColin Finck if(cspace) {
694*c2c66affSColin Finck free_rangepoint(iter);
695*c2c66affSColin Finck *iter = last_space;
696*c2c66affSColin Finck return cspace;
697*c2c66affSColin Finck }
698*c2c66affSColin Finck
699*c2c66affSColin Finck iter->off--;
700*c2c66affSColin Finck return '\n';
701*c2c66affSColin Finck }
702*c2c66affSColin Finck
703*c2c66affSColin Finck nsIDOMNode_Release(node);
704*c2c66affSColin Finck }
705*c2c66affSColin Finck }while(rangepoint_prev_node(iter));
706*c2c66affSColin Finck
707*c2c66affSColin Finck if(cspace) {
708*c2c66affSColin Finck free_rangepoint(iter);
709*c2c66affSColin Finck *iter = last_space;
710*c2c66affSColin Finck return cspace;
711*c2c66affSColin Finck }
712*c2c66affSColin Finck
713*c2c66affSColin Finck return 0;
714*c2c66affSColin Finck }
715*c2c66affSColin Finck
move_by_chars(rangepoint_t * iter,LONG cnt)716*c2c66affSColin Finck static LONG move_by_chars(rangepoint_t *iter, LONG cnt)
717*c2c66affSColin Finck {
718*c2c66affSColin Finck LONG ret = 0;
719*c2c66affSColin Finck
720*c2c66affSColin Finck if(cnt >= 0) {
721*c2c66affSColin Finck while(ret < cnt && move_next_char(iter))
722*c2c66affSColin Finck ret++;
723*c2c66affSColin Finck }else {
724*c2c66affSColin Finck while(ret > cnt && move_prev_char(iter))
725*c2c66affSColin Finck ret--;
726*c2c66affSColin Finck }
727*c2c66affSColin Finck
728*c2c66affSColin Finck return ret;
729*c2c66affSColin Finck }
730*c2c66affSColin Finck
find_prev_space(rangepoint_t * iter,BOOL first_space)731*c2c66affSColin Finck static LONG find_prev_space(rangepoint_t *iter, BOOL first_space)
732*c2c66affSColin Finck {
733*c2c66affSColin Finck rangepoint_t prev;
734*c2c66affSColin Finck WCHAR c;
735*c2c66affSColin Finck
736*c2c66affSColin Finck init_rangepoint(&prev, iter->node, iter->off);
737*c2c66affSColin Finck c = move_prev_char(&prev);
738*c2c66affSColin Finck if(!c || (first_space && isspaceW(c)))
739*c2c66affSColin Finck return FALSE;
740*c2c66affSColin Finck
741*c2c66affSColin Finck do {
742*c2c66affSColin Finck free_rangepoint(iter);
743*c2c66affSColin Finck init_rangepoint(iter, prev.node, prev.off);
744*c2c66affSColin Finck c = move_prev_char(&prev);
745*c2c66affSColin Finck }while(c && !isspaceW(c));
746*c2c66affSColin Finck
747*c2c66affSColin Finck free_rangepoint(&prev);
748*c2c66affSColin Finck return TRUE;
749*c2c66affSColin Finck }
750*c2c66affSColin Finck
find_word_end(rangepoint_t * iter,BOOL is_collapsed)751*c2c66affSColin Finck static BOOL find_word_end(rangepoint_t *iter, BOOL is_collapsed)
752*c2c66affSColin Finck {
753*c2c66affSColin Finck rangepoint_t prev_iter;
754*c2c66affSColin Finck WCHAR c;
755*c2c66affSColin Finck BOOL ret = FALSE;
756*c2c66affSColin Finck
757*c2c66affSColin Finck if(!is_collapsed) {
758*c2c66affSColin Finck init_rangepoint(&prev_iter, iter->node, iter->off);
759*c2c66affSColin Finck c = move_prev_char(&prev_iter);
760*c2c66affSColin Finck free_rangepoint(&prev_iter);
761*c2c66affSColin Finck if(isspaceW(c))
762*c2c66affSColin Finck return FALSE;
763*c2c66affSColin Finck }
764*c2c66affSColin Finck
765*c2c66affSColin Finck do {
766*c2c66affSColin Finck init_rangepoint(&prev_iter, iter->node, iter->off);
767*c2c66affSColin Finck c = move_next_char(iter);
768*c2c66affSColin Finck if(c == '\n') {
769*c2c66affSColin Finck free_rangepoint(iter);
770*c2c66affSColin Finck *iter = prev_iter;
771*c2c66affSColin Finck return ret;
772*c2c66affSColin Finck }
773*c2c66affSColin Finck if(!c) {
774*c2c66affSColin Finck if(!ret)
775*c2c66affSColin Finck ret = !rangepoint_cmp(iter, &prev_iter);
776*c2c66affSColin Finck }else {
777*c2c66affSColin Finck ret = TRUE;
778*c2c66affSColin Finck }
779*c2c66affSColin Finck free_rangepoint(&prev_iter);
780*c2c66affSColin Finck }while(c && !isspaceW(c));
781*c2c66affSColin Finck
782*c2c66affSColin Finck return ret;
783*c2c66affSColin Finck }
784*c2c66affSColin Finck
move_by_words(rangepoint_t * iter,LONG cnt)785*c2c66affSColin Finck static LONG move_by_words(rangepoint_t *iter, LONG cnt)
786*c2c66affSColin Finck {
787*c2c66affSColin Finck LONG ret = 0;
788*c2c66affSColin Finck
789*c2c66affSColin Finck if(cnt >= 0) {
790*c2c66affSColin Finck WCHAR c;
791*c2c66affSColin Finck
792*c2c66affSColin Finck while(ret < cnt && (c = move_next_char(iter))) {
793*c2c66affSColin Finck if(isspaceW(c))
794*c2c66affSColin Finck ret++;
795*c2c66affSColin Finck }
796*c2c66affSColin Finck }else {
797*c2c66affSColin Finck while(ret > cnt && find_prev_space(iter, FALSE))
798*c2c66affSColin Finck ret--;
799*c2c66affSColin Finck }
800*c2c66affSColin Finck
801*c2c66affSColin Finck return ret;
802*c2c66affSColin Finck }
803*c2c66affSColin Finck
impl_from_IHTMLTxtRange(IHTMLTxtRange * iface)804*c2c66affSColin Finck static inline HTMLTxtRange *impl_from_IHTMLTxtRange(IHTMLTxtRange *iface)
805*c2c66affSColin Finck {
806*c2c66affSColin Finck return CONTAINING_RECORD(iface, HTMLTxtRange, IHTMLTxtRange_iface);
807*c2c66affSColin Finck }
808*c2c66affSColin Finck
HTMLTxtRange_QueryInterface(IHTMLTxtRange * iface,REFIID riid,void ** ppv)809*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_QueryInterface(IHTMLTxtRange *iface, REFIID riid, void **ppv)
810*c2c66affSColin Finck {
811*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
812*c2c66affSColin Finck
813*c2c66affSColin Finck TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
814*c2c66affSColin Finck
815*c2c66affSColin Finck if(IsEqualGUID(&IID_IUnknown, riid)) {
816*c2c66affSColin Finck *ppv = &This->IHTMLTxtRange_iface;
817*c2c66affSColin Finck }else if(IsEqualGUID(&IID_IHTMLTxtRange, riid)) {
818*c2c66affSColin Finck *ppv = &This->IHTMLTxtRange_iface;
819*c2c66affSColin Finck }else if(IsEqualGUID(&IID_IOleCommandTarget, riid)) {
820*c2c66affSColin Finck *ppv = &This->IOleCommandTarget_iface;
821*c2c66affSColin Finck }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
822*c2c66affSColin Finck return *ppv ? S_OK : E_NOINTERFACE;
823*c2c66affSColin Finck }else {
824*c2c66affSColin Finck *ppv = NULL;
825*c2c66affSColin Finck WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
826*c2c66affSColin Finck return E_NOINTERFACE;
827*c2c66affSColin Finck }
828*c2c66affSColin Finck
829*c2c66affSColin Finck IUnknown_AddRef((IUnknown*)*ppv);
830*c2c66affSColin Finck return S_OK;
831*c2c66affSColin Finck }
832*c2c66affSColin Finck
HTMLTxtRange_AddRef(IHTMLTxtRange * iface)833*c2c66affSColin Finck static ULONG WINAPI HTMLTxtRange_AddRef(IHTMLTxtRange *iface)
834*c2c66affSColin Finck {
835*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
836*c2c66affSColin Finck LONG ref = InterlockedIncrement(&This->ref);
837*c2c66affSColin Finck
838*c2c66affSColin Finck TRACE("(%p) ref=%d\n", This, ref);
839*c2c66affSColin Finck
840*c2c66affSColin Finck return ref;
841*c2c66affSColin Finck }
842*c2c66affSColin Finck
HTMLTxtRange_Release(IHTMLTxtRange * iface)843*c2c66affSColin Finck static ULONG WINAPI HTMLTxtRange_Release(IHTMLTxtRange *iface)
844*c2c66affSColin Finck {
845*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
846*c2c66affSColin Finck LONG ref = InterlockedDecrement(&This->ref);
847*c2c66affSColin Finck
848*c2c66affSColin Finck TRACE("(%p) ref=%d\n", This, ref);
849*c2c66affSColin Finck
850*c2c66affSColin Finck if(!ref) {
851*c2c66affSColin Finck if(This->nsrange)
852*c2c66affSColin Finck nsIDOMRange_Release(This->nsrange);
853*c2c66affSColin Finck if(This->doc)
854*c2c66affSColin Finck list_remove(&This->entry);
855*c2c66affSColin Finck release_dispex(&This->dispex);
856*c2c66affSColin Finck heap_free(This);
857*c2c66affSColin Finck }
858*c2c66affSColin Finck
859*c2c66affSColin Finck return ref;
860*c2c66affSColin Finck }
861*c2c66affSColin Finck
HTMLTxtRange_GetTypeInfoCount(IHTMLTxtRange * iface,UINT * pctinfo)862*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_GetTypeInfoCount(IHTMLTxtRange *iface, UINT *pctinfo)
863*c2c66affSColin Finck {
864*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
865*c2c66affSColin Finck
866*c2c66affSColin Finck return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
867*c2c66affSColin Finck }
868*c2c66affSColin Finck
HTMLTxtRange_GetTypeInfo(IHTMLTxtRange * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)869*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_GetTypeInfo(IHTMLTxtRange *iface, UINT iTInfo,
870*c2c66affSColin Finck LCID lcid, ITypeInfo **ppTInfo)
871*c2c66affSColin Finck {
872*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
873*c2c66affSColin Finck
874*c2c66affSColin Finck return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
875*c2c66affSColin Finck }
876*c2c66affSColin Finck
HTMLTxtRange_GetIDsOfNames(IHTMLTxtRange * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)877*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_GetIDsOfNames(IHTMLTxtRange *iface, REFIID riid,
878*c2c66affSColin Finck LPOLESTR *rgszNames, UINT cNames,
879*c2c66affSColin Finck LCID lcid, DISPID *rgDispId)
880*c2c66affSColin Finck {
881*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
882*c2c66affSColin Finck
883*c2c66affSColin Finck return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames,
884*c2c66affSColin Finck cNames, lcid, rgDispId);
885*c2c66affSColin Finck }
886*c2c66affSColin Finck
HTMLTxtRange_Invoke(IHTMLTxtRange * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)887*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_Invoke(IHTMLTxtRange *iface, DISPID dispIdMember,
888*c2c66affSColin Finck REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
889*c2c66affSColin Finck VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
890*c2c66affSColin Finck {
891*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
892*c2c66affSColin Finck
893*c2c66affSColin Finck return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid,
894*c2c66affSColin Finck lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
895*c2c66affSColin Finck }
896*c2c66affSColin Finck
HTMLTxtRange_get_htmlText(IHTMLTxtRange * iface,BSTR * p)897*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_get_htmlText(IHTMLTxtRange *iface, BSTR *p)
898*c2c66affSColin Finck {
899*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
900*c2c66affSColin Finck
901*c2c66affSColin Finck TRACE("(%p)->(%p)\n", This, p);
902*c2c66affSColin Finck
903*c2c66affSColin Finck *p = NULL;
904*c2c66affSColin Finck
905*c2c66affSColin Finck if(This->nsrange) {
906*c2c66affSColin Finck nsIDOMDocumentFragment *fragment;
907*c2c66affSColin Finck nsresult nsres;
908*c2c66affSColin Finck
909*c2c66affSColin Finck nsres = nsIDOMRange_CloneContents(This->nsrange, &fragment);
910*c2c66affSColin Finck if(NS_SUCCEEDED(nsres)) {
911*c2c66affSColin Finck const PRUnichar *nstext;
912*c2c66affSColin Finck nsAString nsstr;
913*c2c66affSColin Finck
914*c2c66affSColin Finck nsAString_Init(&nsstr, NULL);
915*c2c66affSColin Finck nsnode_to_nsstring((nsIDOMNode*)fragment, &nsstr);
916*c2c66affSColin Finck nsIDOMDocumentFragment_Release(fragment);
917*c2c66affSColin Finck
918*c2c66affSColin Finck nsAString_GetData(&nsstr, &nstext);
919*c2c66affSColin Finck *p = SysAllocString(nstext);
920*c2c66affSColin Finck
921*c2c66affSColin Finck nsAString_Finish(&nsstr);
922*c2c66affSColin Finck }
923*c2c66affSColin Finck }
924*c2c66affSColin Finck
925*c2c66affSColin Finck if(!*p) {
926*c2c66affSColin Finck const WCHAR emptyW[] = {0};
927*c2c66affSColin Finck *p = SysAllocString(emptyW);
928*c2c66affSColin Finck }
929*c2c66affSColin Finck
930*c2c66affSColin Finck TRACE("return %s\n", debugstr_w(*p));
931*c2c66affSColin Finck return S_OK;
932*c2c66affSColin Finck }
933*c2c66affSColin Finck
HTMLTxtRange_put_text(IHTMLTxtRange * iface,BSTR v)934*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_put_text(IHTMLTxtRange *iface, BSTR v)
935*c2c66affSColin Finck {
936*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
937*c2c66affSColin Finck nsIDOMText *text_node;
938*c2c66affSColin Finck nsAString text_str;
939*c2c66affSColin Finck nsresult nsres;
940*c2c66affSColin Finck
941*c2c66affSColin Finck TRACE("(%p)->(%s)\n", This, debugstr_w(v));
942*c2c66affSColin Finck
943*c2c66affSColin Finck if(!This->doc)
944*c2c66affSColin Finck return MSHTML_E_NODOC;
945*c2c66affSColin Finck
946*c2c66affSColin Finck nsAString_InitDepend(&text_str, v);
947*c2c66affSColin Finck nsres = nsIDOMHTMLDocument_CreateTextNode(This->doc->nsdoc, &text_str, &text_node);
948*c2c66affSColin Finck nsAString_Finish(&text_str);
949*c2c66affSColin Finck if(NS_FAILED(nsres)) {
950*c2c66affSColin Finck ERR("CreateTextNode failed: %08x\n", nsres);
951*c2c66affSColin Finck return S_OK;
952*c2c66affSColin Finck }
953*c2c66affSColin Finck nsres = nsIDOMRange_DeleteContents(This->nsrange);
954*c2c66affSColin Finck if(NS_FAILED(nsres))
955*c2c66affSColin Finck ERR("DeleteContents failed: %08x\n", nsres);
956*c2c66affSColin Finck
957*c2c66affSColin Finck nsres = nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)text_node);
958*c2c66affSColin Finck if(NS_FAILED(nsres))
959*c2c66affSColin Finck ERR("InsertNode failed: %08x\n", nsres);
960*c2c66affSColin Finck
961*c2c66affSColin Finck nsres = nsIDOMRange_SetEndAfter(This->nsrange, (nsIDOMNode*)text_node);
962*c2c66affSColin Finck if(NS_FAILED(nsres))
963*c2c66affSColin Finck ERR("SetEndAfter failed: %08x\n", nsres);
964*c2c66affSColin Finck
965*c2c66affSColin Finck return IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_FALSE);
966*c2c66affSColin Finck }
967*c2c66affSColin Finck
HTMLTxtRange_get_text(IHTMLTxtRange * iface,BSTR * p)968*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_get_text(IHTMLTxtRange *iface, BSTR *p)
969*c2c66affSColin Finck {
970*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
971*c2c66affSColin Finck wstrbuf_t buf;
972*c2c66affSColin Finck
973*c2c66affSColin Finck TRACE("(%p)->(%p)\n", This, p);
974*c2c66affSColin Finck
975*c2c66affSColin Finck *p = NULL;
976*c2c66affSColin Finck if(!This->nsrange)
977*c2c66affSColin Finck return S_OK;
978*c2c66affSColin Finck
979*c2c66affSColin Finck if (!wstrbuf_init(&buf))
980*c2c66affSColin Finck return E_OUTOFMEMORY;
981*c2c66affSColin Finck range_to_string(This, &buf);
982*c2c66affSColin Finck if (buf.buf)
983*c2c66affSColin Finck *p = SysAllocString(buf.buf);
984*c2c66affSColin Finck wstrbuf_finish(&buf);
985*c2c66affSColin Finck
986*c2c66affSColin Finck TRACE("ret %s\n", debugstr_w(*p));
987*c2c66affSColin Finck return S_OK;
988*c2c66affSColin Finck }
989*c2c66affSColin Finck
HTMLTxtRange_parentElement(IHTMLTxtRange * iface,IHTMLElement ** parent)990*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_parentElement(IHTMLTxtRange *iface, IHTMLElement **parent)
991*c2c66affSColin Finck {
992*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
993*c2c66affSColin Finck nsIDOMNode *nsnode, *tmp;
994*c2c66affSColin Finck HTMLDOMNode *node;
995*c2c66affSColin Finck HRESULT hres;
996*c2c66affSColin Finck
997*c2c66affSColin Finck TRACE("(%p)->(%p)\n", This, parent);
998*c2c66affSColin Finck
999*c2c66affSColin Finck nsIDOMRange_GetCommonAncestorContainer(This->nsrange, &nsnode);
1000*c2c66affSColin Finck while(nsnode && get_node_type(nsnode) != ELEMENT_NODE) {
1001*c2c66affSColin Finck nsIDOMNode_GetParentNode(nsnode, &tmp);
1002*c2c66affSColin Finck nsIDOMNode_Release(nsnode);
1003*c2c66affSColin Finck nsnode = tmp;
1004*c2c66affSColin Finck }
1005*c2c66affSColin Finck
1006*c2c66affSColin Finck if(!nsnode) {
1007*c2c66affSColin Finck *parent = NULL;
1008*c2c66affSColin Finck return S_OK;
1009*c2c66affSColin Finck }
1010*c2c66affSColin Finck
1011*c2c66affSColin Finck hres = get_node(This->doc, nsnode, TRUE, &node);
1012*c2c66affSColin Finck nsIDOMNode_Release(nsnode);
1013*c2c66affSColin Finck if(FAILED(hres))
1014*c2c66affSColin Finck return hres;
1015*c2c66affSColin Finck
1016*c2c66affSColin Finck hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface, &IID_IHTMLElement, (void**)parent);
1017*c2c66affSColin Finck node_release(node);
1018*c2c66affSColin Finck return hres;
1019*c2c66affSColin Finck }
1020*c2c66affSColin Finck
HTMLTxtRange_duplicate(IHTMLTxtRange * iface,IHTMLTxtRange ** Duplicate)1021*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_duplicate(IHTMLTxtRange *iface, IHTMLTxtRange **Duplicate)
1022*c2c66affSColin Finck {
1023*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1024*c2c66affSColin Finck nsIDOMRange *nsrange = NULL;
1025*c2c66affSColin Finck HRESULT hres;
1026*c2c66affSColin Finck
1027*c2c66affSColin Finck TRACE("(%p)->(%p)\n", This, Duplicate);
1028*c2c66affSColin Finck
1029*c2c66affSColin Finck nsIDOMRange_CloneRange(This->nsrange, &nsrange);
1030*c2c66affSColin Finck hres = HTMLTxtRange_Create(This->doc, nsrange, Duplicate);
1031*c2c66affSColin Finck nsIDOMRange_Release(nsrange);
1032*c2c66affSColin Finck
1033*c2c66affSColin Finck return hres;
1034*c2c66affSColin Finck }
1035*c2c66affSColin Finck
HTMLTxtRange_inRange(IHTMLTxtRange * iface,IHTMLTxtRange * Range,VARIANT_BOOL * InRange)1036*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_inRange(IHTMLTxtRange *iface, IHTMLTxtRange *Range,
1037*c2c66affSColin Finck VARIANT_BOOL *InRange)
1038*c2c66affSColin Finck {
1039*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1040*c2c66affSColin Finck HTMLTxtRange *src_range;
1041*c2c66affSColin Finck short nsret = 0;
1042*c2c66affSColin Finck nsresult nsres;
1043*c2c66affSColin Finck
1044*c2c66affSColin Finck TRACE("(%p)->(%p %p)\n", This, Range, InRange);
1045*c2c66affSColin Finck
1046*c2c66affSColin Finck *InRange = VARIANT_FALSE;
1047*c2c66affSColin Finck
1048*c2c66affSColin Finck src_range = get_range_object(This->doc, Range);
1049*c2c66affSColin Finck if(!src_range)
1050*c2c66affSColin Finck return E_FAIL;
1051*c2c66affSColin Finck
1052*c2c66affSColin Finck nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_START_TO_START,
1053*c2c66affSColin Finck src_range->nsrange, &nsret);
1054*c2c66affSColin Finck if(NS_SUCCEEDED(nsres) && nsret <= 0) {
1055*c2c66affSColin Finck nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_END_TO_END,
1056*c2c66affSColin Finck src_range->nsrange, &nsret);
1057*c2c66affSColin Finck if(NS_SUCCEEDED(nsres) && nsret >= 0)
1058*c2c66affSColin Finck *InRange = VARIANT_TRUE;
1059*c2c66affSColin Finck }
1060*c2c66affSColin Finck
1061*c2c66affSColin Finck if(NS_FAILED(nsres))
1062*c2c66affSColin Finck ERR("CompareBoundaryPoints failed: %08x\n", nsres);
1063*c2c66affSColin Finck
1064*c2c66affSColin Finck return S_OK;
1065*c2c66affSColin Finck }
1066*c2c66affSColin Finck
HTMLTxtRange_isEqual(IHTMLTxtRange * iface,IHTMLTxtRange * Range,VARIANT_BOOL * IsEqual)1067*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_isEqual(IHTMLTxtRange *iface, IHTMLTxtRange *Range,
1068*c2c66affSColin Finck VARIANT_BOOL *IsEqual)
1069*c2c66affSColin Finck {
1070*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1071*c2c66affSColin Finck HTMLTxtRange *src_range;
1072*c2c66affSColin Finck short nsret = 0;
1073*c2c66affSColin Finck nsresult nsres;
1074*c2c66affSColin Finck
1075*c2c66affSColin Finck TRACE("(%p)->(%p %p)\n", This, Range, IsEqual);
1076*c2c66affSColin Finck
1077*c2c66affSColin Finck *IsEqual = VARIANT_FALSE;
1078*c2c66affSColin Finck
1079*c2c66affSColin Finck src_range = get_range_object(This->doc, Range);
1080*c2c66affSColin Finck if(!src_range)
1081*c2c66affSColin Finck return E_FAIL;
1082*c2c66affSColin Finck
1083*c2c66affSColin Finck nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_START_TO_START,
1084*c2c66affSColin Finck src_range->nsrange, &nsret);
1085*c2c66affSColin Finck if(NS_SUCCEEDED(nsres) && !nsret) {
1086*c2c66affSColin Finck nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, NS_END_TO_END,
1087*c2c66affSColin Finck src_range->nsrange, &nsret);
1088*c2c66affSColin Finck if(NS_SUCCEEDED(nsres) && !nsret)
1089*c2c66affSColin Finck *IsEqual = VARIANT_TRUE;
1090*c2c66affSColin Finck }
1091*c2c66affSColin Finck
1092*c2c66affSColin Finck if(NS_FAILED(nsres))
1093*c2c66affSColin Finck ERR("CompareBoundaryPoints failed: %08x\n", nsres);
1094*c2c66affSColin Finck
1095*c2c66affSColin Finck return S_OK;
1096*c2c66affSColin Finck }
1097*c2c66affSColin Finck
HTMLTxtRange_scrollIntoView(IHTMLTxtRange * iface,VARIANT_BOOL fStart)1098*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_scrollIntoView(IHTMLTxtRange *iface, VARIANT_BOOL fStart)
1099*c2c66affSColin Finck {
1100*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1101*c2c66affSColin Finck FIXME("(%p)->(%x)\n", This, fStart);
1102*c2c66affSColin Finck return E_NOTIMPL;
1103*c2c66affSColin Finck }
1104*c2c66affSColin Finck
HTMLTxtRange_collapse(IHTMLTxtRange * iface,VARIANT_BOOL Start)1105*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_collapse(IHTMLTxtRange *iface, VARIANT_BOOL Start)
1106*c2c66affSColin Finck {
1107*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1108*c2c66affSColin Finck
1109*c2c66affSColin Finck TRACE("(%p)->(%x)\n", This, Start);
1110*c2c66affSColin Finck
1111*c2c66affSColin Finck nsIDOMRange_Collapse(This->nsrange, Start != VARIANT_FALSE);
1112*c2c66affSColin Finck return S_OK;
1113*c2c66affSColin Finck }
1114*c2c66affSColin Finck
HTMLTxtRange_expand(IHTMLTxtRange * iface,BSTR Unit,VARIANT_BOOL * Success)1115*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_expand(IHTMLTxtRange *iface, BSTR Unit, VARIANT_BOOL *Success)
1116*c2c66affSColin Finck {
1117*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1118*c2c66affSColin Finck range_unit_t unit;
1119*c2c66affSColin Finck
1120*c2c66affSColin Finck TRACE("(%p)->(%s %p)\n", This, debugstr_w(Unit), Success);
1121*c2c66affSColin Finck
1122*c2c66affSColin Finck unit = string_to_unit(Unit);
1123*c2c66affSColin Finck if(unit == RU_UNKNOWN)
1124*c2c66affSColin Finck return E_INVALIDARG;
1125*c2c66affSColin Finck
1126*c2c66affSColin Finck *Success = VARIANT_FALSE;
1127*c2c66affSColin Finck
1128*c2c66affSColin Finck switch(unit) {
1129*c2c66affSColin Finck case RU_WORD: {
1130*c2c66affSColin Finck rangepoint_t end, start;
1131*c2c66affSColin Finck cpp_bool is_collapsed;
1132*c2c66affSColin Finck
1133*c2c66affSColin Finck get_start_point(This, &start);
1134*c2c66affSColin Finck get_end_point(This, &end);
1135*c2c66affSColin Finck
1136*c2c66affSColin Finck nsIDOMRange_GetCollapsed(This->nsrange, &is_collapsed);
1137*c2c66affSColin Finck
1138*c2c66affSColin Finck if(find_word_end(&end, is_collapsed)) {
1139*c2c66affSColin Finck set_end_point(This, &end);
1140*c2c66affSColin Finck *Success = VARIANT_TRUE;
1141*c2c66affSColin Finck }
1142*c2c66affSColin Finck
1143*c2c66affSColin Finck if(find_prev_space(&start, TRUE)) {
1144*c2c66affSColin Finck set_start_point(This, &start);
1145*c2c66affSColin Finck *Success = VARIANT_TRUE;
1146*c2c66affSColin Finck }
1147*c2c66affSColin Finck
1148*c2c66affSColin Finck free_rangepoint(&end);
1149*c2c66affSColin Finck free_rangepoint(&start);
1150*c2c66affSColin Finck break;
1151*c2c66affSColin Finck }
1152*c2c66affSColin Finck
1153*c2c66affSColin Finck case RU_TEXTEDIT: {
1154*c2c66affSColin Finck nsIDOMHTMLElement *nsbody = NULL;
1155*c2c66affSColin Finck nsresult nsres;
1156*c2c66affSColin Finck
1157*c2c66affSColin Finck nsres = nsIDOMHTMLDocument_GetBody(This->doc->nsdoc, &nsbody);
1158*c2c66affSColin Finck if(NS_FAILED(nsres) || !nsbody) {
1159*c2c66affSColin Finck ERR("Could not get body: %08x\n", nsres);
1160*c2c66affSColin Finck break;
1161*c2c66affSColin Finck }
1162*c2c66affSColin Finck
1163*c2c66affSColin Finck nsres = nsIDOMRange_SelectNodeContents(This->nsrange, (nsIDOMNode*)nsbody);
1164*c2c66affSColin Finck nsIDOMHTMLElement_Release(nsbody);
1165*c2c66affSColin Finck if(NS_FAILED(nsres)) {
1166*c2c66affSColin Finck ERR("Collapse failed: %08x\n", nsres);
1167*c2c66affSColin Finck break;
1168*c2c66affSColin Finck }
1169*c2c66affSColin Finck
1170*c2c66affSColin Finck *Success = VARIANT_TRUE;
1171*c2c66affSColin Finck break;
1172*c2c66affSColin Finck }
1173*c2c66affSColin Finck
1174*c2c66affSColin Finck default:
1175*c2c66affSColin Finck FIXME("Unimplemented unit %s\n", debugstr_w(Unit));
1176*c2c66affSColin Finck }
1177*c2c66affSColin Finck
1178*c2c66affSColin Finck return S_OK;
1179*c2c66affSColin Finck }
1180*c2c66affSColin Finck
HTMLTxtRange_move(IHTMLTxtRange * iface,BSTR Unit,LONG Count,LONG * ActualCount)1181*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_move(IHTMLTxtRange *iface, BSTR Unit,
1182*c2c66affSColin Finck LONG Count, LONG *ActualCount)
1183*c2c66affSColin Finck {
1184*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1185*c2c66affSColin Finck range_unit_t unit;
1186*c2c66affSColin Finck
1187*c2c66affSColin Finck TRACE("(%p)->(%s %d %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1188*c2c66affSColin Finck
1189*c2c66affSColin Finck unit = string_to_unit(Unit);
1190*c2c66affSColin Finck if(unit == RU_UNKNOWN)
1191*c2c66affSColin Finck return E_INVALIDARG;
1192*c2c66affSColin Finck
1193*c2c66affSColin Finck if(!Count) {
1194*c2c66affSColin Finck *ActualCount = 0;
1195*c2c66affSColin Finck return IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1196*c2c66affSColin Finck }
1197*c2c66affSColin Finck
1198*c2c66affSColin Finck switch(unit) {
1199*c2c66affSColin Finck case RU_CHAR: {
1200*c2c66affSColin Finck rangepoint_t start;
1201*c2c66affSColin Finck
1202*c2c66affSColin Finck get_start_point(This, &start);
1203*c2c66affSColin Finck
1204*c2c66affSColin Finck *ActualCount = move_by_chars(&start, Count);
1205*c2c66affSColin Finck
1206*c2c66affSColin Finck set_start_point(This, &start);
1207*c2c66affSColin Finck IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1208*c2c66affSColin Finck free_rangepoint(&start);
1209*c2c66affSColin Finck break;
1210*c2c66affSColin Finck }
1211*c2c66affSColin Finck
1212*c2c66affSColin Finck case RU_WORD: {
1213*c2c66affSColin Finck rangepoint_t start;
1214*c2c66affSColin Finck
1215*c2c66affSColin Finck get_start_point(This, &start);
1216*c2c66affSColin Finck
1217*c2c66affSColin Finck *ActualCount = move_by_words(&start, Count);
1218*c2c66affSColin Finck
1219*c2c66affSColin Finck set_start_point(This, &start);
1220*c2c66affSColin Finck IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, VARIANT_TRUE);
1221*c2c66affSColin Finck free_rangepoint(&start);
1222*c2c66affSColin Finck break;
1223*c2c66affSColin Finck }
1224*c2c66affSColin Finck
1225*c2c66affSColin Finck default:
1226*c2c66affSColin Finck FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1227*c2c66affSColin Finck }
1228*c2c66affSColin Finck
1229*c2c66affSColin Finck TRACE("ret %d\n", *ActualCount);
1230*c2c66affSColin Finck return S_OK;
1231*c2c66affSColin Finck }
1232*c2c66affSColin Finck
HTMLTxtRange_moveStart(IHTMLTxtRange * iface,BSTR Unit,LONG Count,LONG * ActualCount)1233*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_moveStart(IHTMLTxtRange *iface, BSTR Unit,
1234*c2c66affSColin Finck LONG Count, LONG *ActualCount)
1235*c2c66affSColin Finck {
1236*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1237*c2c66affSColin Finck range_unit_t unit;
1238*c2c66affSColin Finck
1239*c2c66affSColin Finck TRACE("(%p)->(%s %d %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1240*c2c66affSColin Finck
1241*c2c66affSColin Finck unit = string_to_unit(Unit);
1242*c2c66affSColin Finck if(unit == RU_UNKNOWN)
1243*c2c66affSColin Finck return E_INVALIDARG;
1244*c2c66affSColin Finck
1245*c2c66affSColin Finck if(!Count) {
1246*c2c66affSColin Finck *ActualCount = 0;
1247*c2c66affSColin Finck return S_OK;
1248*c2c66affSColin Finck }
1249*c2c66affSColin Finck
1250*c2c66affSColin Finck switch(unit) {
1251*c2c66affSColin Finck case RU_CHAR: {
1252*c2c66affSColin Finck rangepoint_t start;
1253*c2c66affSColin Finck
1254*c2c66affSColin Finck get_start_point(This, &start);
1255*c2c66affSColin Finck
1256*c2c66affSColin Finck *ActualCount = move_by_chars(&start, Count);
1257*c2c66affSColin Finck
1258*c2c66affSColin Finck set_start_point(This, &start);
1259*c2c66affSColin Finck free_rangepoint(&start);
1260*c2c66affSColin Finck break;
1261*c2c66affSColin Finck }
1262*c2c66affSColin Finck
1263*c2c66affSColin Finck default:
1264*c2c66affSColin Finck FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1265*c2c66affSColin Finck return E_NOTIMPL;
1266*c2c66affSColin Finck }
1267*c2c66affSColin Finck
1268*c2c66affSColin Finck return S_OK;
1269*c2c66affSColin Finck }
1270*c2c66affSColin Finck
HTMLTxtRange_moveEnd(IHTMLTxtRange * iface,BSTR Unit,LONG Count,LONG * ActualCount)1271*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_moveEnd(IHTMLTxtRange *iface, BSTR Unit,
1272*c2c66affSColin Finck LONG Count, LONG *ActualCount)
1273*c2c66affSColin Finck {
1274*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1275*c2c66affSColin Finck range_unit_t unit;
1276*c2c66affSColin Finck
1277*c2c66affSColin Finck TRACE("(%p)->(%s %d %p)\n", This, debugstr_w(Unit), Count, ActualCount);
1278*c2c66affSColin Finck
1279*c2c66affSColin Finck unit = string_to_unit(Unit);
1280*c2c66affSColin Finck if(unit == RU_UNKNOWN)
1281*c2c66affSColin Finck return E_INVALIDARG;
1282*c2c66affSColin Finck
1283*c2c66affSColin Finck if(!Count) {
1284*c2c66affSColin Finck *ActualCount = 0;
1285*c2c66affSColin Finck return S_OK;
1286*c2c66affSColin Finck }
1287*c2c66affSColin Finck
1288*c2c66affSColin Finck switch(unit) {
1289*c2c66affSColin Finck case RU_CHAR: {
1290*c2c66affSColin Finck rangepoint_t end;
1291*c2c66affSColin Finck
1292*c2c66affSColin Finck get_end_point(This, &end);
1293*c2c66affSColin Finck
1294*c2c66affSColin Finck *ActualCount = move_by_chars(&end, Count);
1295*c2c66affSColin Finck
1296*c2c66affSColin Finck set_end_point(This, &end);
1297*c2c66affSColin Finck free_rangepoint(&end);
1298*c2c66affSColin Finck break;
1299*c2c66affSColin Finck }
1300*c2c66affSColin Finck
1301*c2c66affSColin Finck default:
1302*c2c66affSColin Finck FIXME("unimplemented unit %s\n", debugstr_w(Unit));
1303*c2c66affSColin Finck }
1304*c2c66affSColin Finck
1305*c2c66affSColin Finck return S_OK;
1306*c2c66affSColin Finck }
1307*c2c66affSColin Finck
HTMLTxtRange_select(IHTMLTxtRange * iface)1308*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_select(IHTMLTxtRange *iface)
1309*c2c66affSColin Finck {
1310*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1311*c2c66affSColin Finck nsISelection *nsselection;
1312*c2c66affSColin Finck nsresult nsres;
1313*c2c66affSColin Finck
1314*c2c66affSColin Finck TRACE("(%p)\n", This);
1315*c2c66affSColin Finck
1316*c2c66affSColin Finck nsres = nsIDOMWindow_GetSelection(This->doc->basedoc.window->nswindow, &nsselection);
1317*c2c66affSColin Finck if(NS_FAILED(nsres)) {
1318*c2c66affSColin Finck ERR("GetSelection failed: %08x\n", nsres);
1319*c2c66affSColin Finck return E_FAIL;
1320*c2c66affSColin Finck }
1321*c2c66affSColin Finck
1322*c2c66affSColin Finck nsISelection_RemoveAllRanges(nsselection);
1323*c2c66affSColin Finck nsISelection_AddRange(nsselection, This->nsrange);
1324*c2c66affSColin Finck nsISelection_Release(nsselection);
1325*c2c66affSColin Finck return S_OK;
1326*c2c66affSColin Finck }
1327*c2c66affSColin Finck
HTMLTxtRange_pasteHTML(IHTMLTxtRange * iface,BSTR html)1328*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_pasteHTML(IHTMLTxtRange *iface, BSTR html)
1329*c2c66affSColin Finck {
1330*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1331*c2c66affSColin Finck nsIDOMDocumentFragment *doc_frag;
1332*c2c66affSColin Finck nsAString nsstr;
1333*c2c66affSColin Finck nsresult nsres;
1334*c2c66affSColin Finck
1335*c2c66affSColin Finck TRACE("(%p)->(%s)\n", This, debugstr_w(html));
1336*c2c66affSColin Finck
1337*c2c66affSColin Finck nsres = nsIDOMRange_Collapse(This->nsrange, TRUE);
1338*c2c66affSColin Finck assert(nsres == NS_OK);
1339*c2c66affSColin Finck
1340*c2c66affSColin Finck nsAString_InitDepend(&nsstr, html);
1341*c2c66affSColin Finck nsres = nsIDOMRange_CreateContextualFragment(This->nsrange, &nsstr, &doc_frag);
1342*c2c66affSColin Finck nsAString_Finish(&nsstr);
1343*c2c66affSColin Finck if(NS_FAILED(nsres)) {
1344*c2c66affSColin Finck ERR("CreateContextualFragment failed: %08x\n", nsres);
1345*c2c66affSColin Finck return E_FAIL;
1346*c2c66affSColin Finck }
1347*c2c66affSColin Finck
1348*c2c66affSColin Finck nsres = nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)doc_frag);
1349*c2c66affSColin Finck nsIDOMDocumentFragment_Release(doc_frag);
1350*c2c66affSColin Finck if(NS_FAILED(nsres)) {
1351*c2c66affSColin Finck ERR("InsertNode failed: %08x\n", nsres);
1352*c2c66affSColin Finck return E_FAIL;
1353*c2c66affSColin Finck }
1354*c2c66affSColin Finck
1355*c2c66affSColin Finck nsres = nsIDOMRange_Collapse(This->nsrange, FALSE);
1356*c2c66affSColin Finck assert(nsres == NS_OK);
1357*c2c66affSColin Finck return S_OK;
1358*c2c66affSColin Finck }
1359*c2c66affSColin Finck
HTMLTxtRange_moveToElementText(IHTMLTxtRange * iface,IHTMLElement * element)1360*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_moveToElementText(IHTMLTxtRange *iface, IHTMLElement *element)
1361*c2c66affSColin Finck {
1362*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1363*c2c66affSColin Finck HTMLElement *elem;
1364*c2c66affSColin Finck nsresult nsres;
1365*c2c66affSColin Finck
1366*c2c66affSColin Finck TRACE("(%p)->(%p)\n", This, element);
1367*c2c66affSColin Finck
1368*c2c66affSColin Finck elem = unsafe_impl_from_IHTMLElement(element);
1369*c2c66affSColin Finck if(!elem)
1370*c2c66affSColin Finck return E_INVALIDARG;
1371*c2c66affSColin Finck
1372*c2c66affSColin Finck nsres = nsIDOMRange_SelectNodeContents(This->nsrange, elem->node.nsnode);
1373*c2c66affSColin Finck if(NS_FAILED(nsres)) {
1374*c2c66affSColin Finck ERR("SelectNodeContents failed: %08x\n", nsres);
1375*c2c66affSColin Finck return E_FAIL;
1376*c2c66affSColin Finck }
1377*c2c66affSColin Finck
1378*c2c66affSColin Finck return S_OK;
1379*c2c66affSColin Finck }
1380*c2c66affSColin Finck
HTMLTxtRange_setEndPoint(IHTMLTxtRange * iface,BSTR how,IHTMLTxtRange * SourceRange)1381*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_setEndPoint(IHTMLTxtRange *iface, BSTR how,
1382*c2c66affSColin Finck IHTMLTxtRange *SourceRange)
1383*c2c66affSColin Finck {
1384*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1385*c2c66affSColin Finck HTMLTxtRange *src_range;
1386*c2c66affSColin Finck nsIDOMNode *ref_node;
1387*c2c66affSColin Finck INT32 ref_offset;
1388*c2c66affSColin Finck BOOL set_start;
1389*c2c66affSColin Finck int how_type;
1390*c2c66affSColin Finck INT16 cmp;
1391*c2c66affSColin Finck nsresult nsres;
1392*c2c66affSColin Finck
1393*c2c66affSColin Finck TRACE("(%p)->(%s %p)\n", This, debugstr_w(how), SourceRange);
1394*c2c66affSColin Finck
1395*c2c66affSColin Finck how_type = string_to_nscmptype(how);
1396*c2c66affSColin Finck if(how_type == -1)
1397*c2c66affSColin Finck return E_INVALIDARG;
1398*c2c66affSColin Finck
1399*c2c66affSColin Finck src_range = get_range_object(This->doc, SourceRange);
1400*c2c66affSColin Finck if(!src_range)
1401*c2c66affSColin Finck return E_FAIL;
1402*c2c66affSColin Finck
1403*c2c66affSColin Finck switch(how_type) {
1404*c2c66affSColin Finck case NS_START_TO_START:
1405*c2c66affSColin Finck case NS_END_TO_START:
1406*c2c66affSColin Finck nsres = nsIDOMRange_GetStartContainer(src_range->nsrange, &ref_node);
1407*c2c66affSColin Finck assert(nsres == NS_OK);
1408*c2c66affSColin Finck
1409*c2c66affSColin Finck nsres = nsIDOMRange_GetStartOffset(src_range->nsrange, &ref_offset);
1410*c2c66affSColin Finck assert(nsres == NS_OK);
1411*c2c66affSColin Finck
1412*c2c66affSColin Finck set_start = how_type == NS_START_TO_START;
1413*c2c66affSColin Finck break;
1414*c2c66affSColin Finck case NS_END_TO_END:
1415*c2c66affSColin Finck case NS_START_TO_END:
1416*c2c66affSColin Finck nsres = nsIDOMRange_GetEndContainer(src_range->nsrange, &ref_node);
1417*c2c66affSColin Finck assert(nsres == NS_OK);
1418*c2c66affSColin Finck
1419*c2c66affSColin Finck nsres = nsIDOMRange_GetEndOffset(src_range->nsrange, &ref_offset);
1420*c2c66affSColin Finck assert(nsres == NS_OK);
1421*c2c66affSColin Finck
1422*c2c66affSColin Finck set_start = how_type == NS_START_TO_END;
1423*c2c66affSColin Finck break;
1424*c2c66affSColin Finck DEFAULT_UNREACHABLE;
1425*c2c66affSColin Finck }
1426*c2c66affSColin Finck
1427*c2c66affSColin Finck nsres = nsIDOMRange_ComparePoint(This->nsrange, ref_node, ref_offset, &cmp);
1428*c2c66affSColin Finck assert(nsres == NS_OK);
1429*c2c66affSColin Finck
1430*c2c66affSColin Finck if(set_start) {
1431*c2c66affSColin Finck if(cmp <= 0) {
1432*c2c66affSColin Finck nsres = nsIDOMRange_SetStart(This->nsrange, ref_node, ref_offset);
1433*c2c66affSColin Finck }else {
1434*c2c66affSColin Finck nsres = nsIDOMRange_Collapse(This->nsrange, FALSE);
1435*c2c66affSColin Finck assert(nsres == NS_OK);
1436*c2c66affSColin Finck
1437*c2c66affSColin Finck nsres = nsIDOMRange_SetEnd(This->nsrange, ref_node, ref_offset);
1438*c2c66affSColin Finck }
1439*c2c66affSColin Finck }else {
1440*c2c66affSColin Finck if(cmp >= 0) {
1441*c2c66affSColin Finck nsres = nsIDOMRange_SetEnd(This->nsrange, ref_node, ref_offset);
1442*c2c66affSColin Finck }else {
1443*c2c66affSColin Finck nsres = nsIDOMRange_Collapse(This->nsrange, TRUE);
1444*c2c66affSColin Finck assert(nsres == NS_OK);
1445*c2c66affSColin Finck
1446*c2c66affSColin Finck nsres = nsIDOMRange_SetStart(This->nsrange, ref_node, ref_offset);
1447*c2c66affSColin Finck }
1448*c2c66affSColin Finck }
1449*c2c66affSColin Finck assert(nsres == NS_OK);
1450*c2c66affSColin Finck
1451*c2c66affSColin Finck nsIDOMNode_Release(ref_node);
1452*c2c66affSColin Finck return S_OK;
1453*c2c66affSColin Finck }
1454*c2c66affSColin Finck
HTMLTxtRange_compareEndPoints(IHTMLTxtRange * iface,BSTR how,IHTMLTxtRange * SourceRange,LONG * ret)1455*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_compareEndPoints(IHTMLTxtRange *iface, BSTR how,
1456*c2c66affSColin Finck IHTMLTxtRange *SourceRange, LONG *ret)
1457*c2c66affSColin Finck {
1458*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1459*c2c66affSColin Finck HTMLTxtRange *src_range;
1460*c2c66affSColin Finck short nsret = 0;
1461*c2c66affSColin Finck int nscmpt;
1462*c2c66affSColin Finck nsresult nsres;
1463*c2c66affSColin Finck
1464*c2c66affSColin Finck TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(how), SourceRange, ret);
1465*c2c66affSColin Finck
1466*c2c66affSColin Finck nscmpt = string_to_nscmptype(how);
1467*c2c66affSColin Finck if(nscmpt == -1)
1468*c2c66affSColin Finck return E_INVALIDARG;
1469*c2c66affSColin Finck
1470*c2c66affSColin Finck src_range = get_range_object(This->doc, SourceRange);
1471*c2c66affSColin Finck if(!src_range)
1472*c2c66affSColin Finck return E_FAIL;
1473*c2c66affSColin Finck
1474*c2c66affSColin Finck nsres = nsIDOMRange_CompareBoundaryPoints(This->nsrange, nscmpt, src_range->nsrange, &nsret);
1475*c2c66affSColin Finck if(NS_FAILED(nsres))
1476*c2c66affSColin Finck ERR("CompareBoundaryPoints failed: %08x\n", nsres);
1477*c2c66affSColin Finck
1478*c2c66affSColin Finck *ret = nsret;
1479*c2c66affSColin Finck return S_OK;
1480*c2c66affSColin Finck }
1481*c2c66affSColin Finck
HTMLTxtRange_findText(IHTMLTxtRange * iface,BSTR String,LONG count,LONG Flags,VARIANT_BOOL * Success)1482*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_findText(IHTMLTxtRange *iface, BSTR String,
1483*c2c66affSColin Finck LONG count, LONG Flags, VARIANT_BOOL *Success)
1484*c2c66affSColin Finck {
1485*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1486*c2c66affSColin Finck FIXME("(%p)->(%s %d %08x %p)\n", This, debugstr_w(String), count, Flags, Success);
1487*c2c66affSColin Finck return E_NOTIMPL;
1488*c2c66affSColin Finck }
1489*c2c66affSColin Finck
HTMLTxtRange_moveToPoint(IHTMLTxtRange * iface,LONG x,LONG y)1490*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_moveToPoint(IHTMLTxtRange *iface, LONG x, LONG y)
1491*c2c66affSColin Finck {
1492*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1493*c2c66affSColin Finck FIXME("(%p)->(%d %d)\n", This, x, y);
1494*c2c66affSColin Finck return E_NOTIMPL;
1495*c2c66affSColin Finck }
1496*c2c66affSColin Finck
HTMLTxtRange_getBookmark(IHTMLTxtRange * iface,BSTR * Bookmark)1497*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_getBookmark(IHTMLTxtRange *iface, BSTR *Bookmark)
1498*c2c66affSColin Finck {
1499*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1500*c2c66affSColin Finck FIXME("(%p)->(%p)\n", This, Bookmark);
1501*c2c66affSColin Finck return E_NOTIMPL;
1502*c2c66affSColin Finck }
1503*c2c66affSColin Finck
HTMLTxtRange_moveToBookmark(IHTMLTxtRange * iface,BSTR Bookmark,VARIANT_BOOL * Success)1504*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_moveToBookmark(IHTMLTxtRange *iface, BSTR Bookmark,
1505*c2c66affSColin Finck VARIANT_BOOL *Success)
1506*c2c66affSColin Finck {
1507*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1508*c2c66affSColin Finck FIXME("(%p)->(%s %p)\n", This, debugstr_w(Bookmark), Success);
1509*c2c66affSColin Finck return E_NOTIMPL;
1510*c2c66affSColin Finck }
1511*c2c66affSColin Finck
HTMLTxtRange_queryCommandSupported(IHTMLTxtRange * iface,BSTR cmdID,VARIANT_BOOL * pfRet)1512*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_queryCommandSupported(IHTMLTxtRange *iface, BSTR cmdID,
1513*c2c66affSColin Finck VARIANT_BOOL *pfRet)
1514*c2c66affSColin Finck {
1515*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1516*c2c66affSColin Finck FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1517*c2c66affSColin Finck return E_NOTIMPL;
1518*c2c66affSColin Finck }
1519*c2c66affSColin Finck
HTMLTxtRange_queryCommandEnabled(IHTMLTxtRange * iface,BSTR cmdID,VARIANT_BOOL * pfRet)1520*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_queryCommandEnabled(IHTMLTxtRange *iface, BSTR cmdID,
1521*c2c66affSColin Finck VARIANT_BOOL *pfRet)
1522*c2c66affSColin Finck {
1523*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1524*c2c66affSColin Finck FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1525*c2c66affSColin Finck return E_NOTIMPL;
1526*c2c66affSColin Finck }
1527*c2c66affSColin Finck
HTMLTxtRange_queryCommandState(IHTMLTxtRange * iface,BSTR cmdID,VARIANT_BOOL * pfRet)1528*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_queryCommandState(IHTMLTxtRange *iface, BSTR cmdID,
1529*c2c66affSColin Finck VARIANT_BOOL *pfRet)
1530*c2c66affSColin Finck {
1531*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1532*c2c66affSColin Finck FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1533*c2c66affSColin Finck return E_NOTIMPL;
1534*c2c66affSColin Finck }
1535*c2c66affSColin Finck
HTMLTxtRange_queryCommandIndeterm(IHTMLTxtRange * iface,BSTR cmdID,VARIANT_BOOL * pfRet)1536*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_queryCommandIndeterm(IHTMLTxtRange *iface, BSTR cmdID,
1537*c2c66affSColin Finck VARIANT_BOOL *pfRet)
1538*c2c66affSColin Finck {
1539*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1540*c2c66affSColin Finck FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1541*c2c66affSColin Finck return E_NOTIMPL;
1542*c2c66affSColin Finck }
1543*c2c66affSColin Finck
HTMLTxtRange_queryCommandText(IHTMLTxtRange * iface,BSTR cmdID,BSTR * pcmdText)1544*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_queryCommandText(IHTMLTxtRange *iface, BSTR cmdID,
1545*c2c66affSColin Finck BSTR *pcmdText)
1546*c2c66affSColin Finck {
1547*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1548*c2c66affSColin Finck FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pcmdText);
1549*c2c66affSColin Finck return E_NOTIMPL;
1550*c2c66affSColin Finck }
1551*c2c66affSColin Finck
HTMLTxtRange_queryCommandValue(IHTMLTxtRange * iface,BSTR cmdID,VARIANT * pcmdValue)1552*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_queryCommandValue(IHTMLTxtRange *iface, BSTR cmdID,
1553*c2c66affSColin Finck VARIANT *pcmdValue)
1554*c2c66affSColin Finck {
1555*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1556*c2c66affSColin Finck FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pcmdValue);
1557*c2c66affSColin Finck return E_NOTIMPL;
1558*c2c66affSColin Finck }
1559*c2c66affSColin Finck
HTMLTxtRange_execCommand(IHTMLTxtRange * iface,BSTR cmdID,VARIANT_BOOL showUI,VARIANT value,VARIANT_BOOL * pfRet)1560*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_execCommand(IHTMLTxtRange *iface, BSTR cmdID,
1561*c2c66affSColin Finck VARIANT_BOOL showUI, VARIANT value, VARIANT_BOOL *pfRet)
1562*c2c66affSColin Finck {
1563*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1564*c2c66affSColin Finck FIXME("(%p)->(%s %x v %p)\n", This, debugstr_w(cmdID), showUI, pfRet);
1565*c2c66affSColin Finck return E_NOTIMPL;
1566*c2c66affSColin Finck }
1567*c2c66affSColin Finck
HTMLTxtRange_execCommandShowHelp(IHTMLTxtRange * iface,BSTR cmdID,VARIANT_BOOL * pfRet)1568*c2c66affSColin Finck static HRESULT WINAPI HTMLTxtRange_execCommandShowHelp(IHTMLTxtRange *iface, BSTR cmdID,
1569*c2c66affSColin Finck VARIANT_BOOL *pfRet)
1570*c2c66affSColin Finck {
1571*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IHTMLTxtRange(iface);
1572*c2c66affSColin Finck FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1573*c2c66affSColin Finck return E_NOTIMPL;
1574*c2c66affSColin Finck }
1575*c2c66affSColin Finck
1576*c2c66affSColin Finck static const IHTMLTxtRangeVtbl HTMLTxtRangeVtbl = {
1577*c2c66affSColin Finck HTMLTxtRange_QueryInterface,
1578*c2c66affSColin Finck HTMLTxtRange_AddRef,
1579*c2c66affSColin Finck HTMLTxtRange_Release,
1580*c2c66affSColin Finck HTMLTxtRange_GetTypeInfoCount,
1581*c2c66affSColin Finck HTMLTxtRange_GetTypeInfo,
1582*c2c66affSColin Finck HTMLTxtRange_GetIDsOfNames,
1583*c2c66affSColin Finck HTMLTxtRange_Invoke,
1584*c2c66affSColin Finck HTMLTxtRange_get_htmlText,
1585*c2c66affSColin Finck HTMLTxtRange_put_text,
1586*c2c66affSColin Finck HTMLTxtRange_get_text,
1587*c2c66affSColin Finck HTMLTxtRange_parentElement,
1588*c2c66affSColin Finck HTMLTxtRange_duplicate,
1589*c2c66affSColin Finck HTMLTxtRange_inRange,
1590*c2c66affSColin Finck HTMLTxtRange_isEqual,
1591*c2c66affSColin Finck HTMLTxtRange_scrollIntoView,
1592*c2c66affSColin Finck HTMLTxtRange_collapse,
1593*c2c66affSColin Finck HTMLTxtRange_expand,
1594*c2c66affSColin Finck HTMLTxtRange_move,
1595*c2c66affSColin Finck HTMLTxtRange_moveStart,
1596*c2c66affSColin Finck HTMLTxtRange_moveEnd,
1597*c2c66affSColin Finck HTMLTxtRange_select,
1598*c2c66affSColin Finck HTMLTxtRange_pasteHTML,
1599*c2c66affSColin Finck HTMLTxtRange_moveToElementText,
1600*c2c66affSColin Finck HTMLTxtRange_setEndPoint,
1601*c2c66affSColin Finck HTMLTxtRange_compareEndPoints,
1602*c2c66affSColin Finck HTMLTxtRange_findText,
1603*c2c66affSColin Finck HTMLTxtRange_moveToPoint,
1604*c2c66affSColin Finck HTMLTxtRange_getBookmark,
1605*c2c66affSColin Finck HTMLTxtRange_moveToBookmark,
1606*c2c66affSColin Finck HTMLTxtRange_queryCommandSupported,
1607*c2c66affSColin Finck HTMLTxtRange_queryCommandEnabled,
1608*c2c66affSColin Finck HTMLTxtRange_queryCommandState,
1609*c2c66affSColin Finck HTMLTxtRange_queryCommandIndeterm,
1610*c2c66affSColin Finck HTMLTxtRange_queryCommandText,
1611*c2c66affSColin Finck HTMLTxtRange_queryCommandValue,
1612*c2c66affSColin Finck HTMLTxtRange_execCommand,
1613*c2c66affSColin Finck HTMLTxtRange_execCommandShowHelp
1614*c2c66affSColin Finck };
1615*c2c66affSColin Finck
impl_from_IOleCommandTarget(IOleCommandTarget * iface)1616*c2c66affSColin Finck static inline HTMLTxtRange *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
1617*c2c66affSColin Finck {
1618*c2c66affSColin Finck return CONTAINING_RECORD(iface, HTMLTxtRange, IOleCommandTarget_iface);
1619*c2c66affSColin Finck }
1620*c2c66affSColin Finck
RangeCommandTarget_QueryInterface(IOleCommandTarget * iface,REFIID riid,void ** ppv)1621*c2c66affSColin Finck static HRESULT WINAPI RangeCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
1622*c2c66affSColin Finck {
1623*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1624*c2c66affSColin Finck return IHTMLTxtRange_QueryInterface(&This->IHTMLTxtRange_iface, riid, ppv);
1625*c2c66affSColin Finck }
1626*c2c66affSColin Finck
RangeCommandTarget_AddRef(IOleCommandTarget * iface)1627*c2c66affSColin Finck static ULONG WINAPI RangeCommandTarget_AddRef(IOleCommandTarget *iface)
1628*c2c66affSColin Finck {
1629*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1630*c2c66affSColin Finck return IHTMLTxtRange_AddRef(&This->IHTMLTxtRange_iface);
1631*c2c66affSColin Finck }
1632*c2c66affSColin Finck
RangeCommandTarget_Release(IOleCommandTarget * iface)1633*c2c66affSColin Finck static ULONG WINAPI RangeCommandTarget_Release(IOleCommandTarget *iface)
1634*c2c66affSColin Finck {
1635*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1636*c2c66affSColin Finck return IHTMLTxtRange_Release(&This->IHTMLTxtRange_iface);
1637*c2c66affSColin Finck }
1638*c2c66affSColin Finck
RangeCommandTarget_QueryStatus(IOleCommandTarget * iface,const GUID * pguidCmdGroup,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT * pCmdText)1639*c2c66affSColin Finck static HRESULT WINAPI RangeCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1640*c2c66affSColin Finck ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
1641*c2c66affSColin Finck {
1642*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1643*c2c66affSColin Finck FIXME("(%p)->(%s %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
1644*c2c66affSColin Finck return E_NOTIMPL;
1645*c2c66affSColin Finck }
1646*c2c66affSColin Finck
exec_indent(HTMLTxtRange * This,VARIANT * in,VARIANT * out)1647*c2c66affSColin Finck static HRESULT exec_indent(HTMLTxtRange *This, VARIANT *in, VARIANT *out)
1648*c2c66affSColin Finck {
1649*c2c66affSColin Finck nsIDOMHTMLElement *blockquote_elem, *p_elem;
1650*c2c66affSColin Finck nsIDOMDocumentFragment *fragment;
1651*c2c66affSColin Finck nsIDOMNode *tmp;
1652*c2c66affSColin Finck
1653*c2c66affSColin Finck static const PRUnichar blockquoteW[] = {'B','L','O','C','K','Q','U','O','T','E',0};
1654*c2c66affSColin Finck static const PRUnichar pW[] = {'P',0};
1655*c2c66affSColin Finck
1656*c2c66affSColin Finck TRACE("(%p)->(%p %p)\n", This, in, out);
1657*c2c66affSColin Finck
1658*c2c66affSColin Finck if(!This->doc->nsdoc) {
1659*c2c66affSColin Finck WARN("NULL nsdoc\n");
1660*c2c66affSColin Finck return E_NOTIMPL;
1661*c2c66affSColin Finck }
1662*c2c66affSColin Finck
1663*c2c66affSColin Finck create_nselem(This->doc, blockquoteW, &blockquote_elem);
1664*c2c66affSColin Finck create_nselem(This->doc, pW, &p_elem);
1665*c2c66affSColin Finck
1666*c2c66affSColin Finck nsIDOMRange_ExtractContents(This->nsrange, &fragment);
1667*c2c66affSColin Finck nsIDOMHTMLElement_AppendChild(p_elem, (nsIDOMNode*)fragment, &tmp);
1668*c2c66affSColin Finck nsIDOMDocumentFragment_Release(fragment);
1669*c2c66affSColin Finck nsIDOMNode_Release(tmp);
1670*c2c66affSColin Finck
1671*c2c66affSColin Finck nsIDOMHTMLElement_AppendChild(blockquote_elem, (nsIDOMNode*)p_elem, &tmp);
1672*c2c66affSColin Finck nsIDOMHTMLElement_Release(p_elem);
1673*c2c66affSColin Finck nsIDOMNode_Release(tmp);
1674*c2c66affSColin Finck
1675*c2c66affSColin Finck nsIDOMRange_InsertNode(This->nsrange, (nsIDOMNode*)blockquote_elem);
1676*c2c66affSColin Finck nsIDOMHTMLElement_Release(blockquote_elem);
1677*c2c66affSColin Finck
1678*c2c66affSColin Finck return S_OK;
1679*c2c66affSColin Finck }
1680*c2c66affSColin Finck
RangeCommandTarget_Exec(IOleCommandTarget * iface,const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)1681*c2c66affSColin Finck static HRESULT WINAPI RangeCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1682*c2c66affSColin Finck DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1683*c2c66affSColin Finck {
1684*c2c66affSColin Finck HTMLTxtRange *This = impl_from_IOleCommandTarget(iface);
1685*c2c66affSColin Finck
1686*c2c66affSColin Finck TRACE("(%p)->(%s %d %x %p %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID,
1687*c2c66affSColin Finck nCmdexecopt, pvaIn, pvaOut);
1688*c2c66affSColin Finck
1689*c2c66affSColin Finck if(pguidCmdGroup && IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
1690*c2c66affSColin Finck switch(nCmdID) {
1691*c2c66affSColin Finck case IDM_INDENT:
1692*c2c66affSColin Finck return exec_indent(This, pvaIn, pvaOut);
1693*c2c66affSColin Finck default:
1694*c2c66affSColin Finck FIXME("Unsupported cmdid %d of CGID_MSHTML\n", nCmdID);
1695*c2c66affSColin Finck }
1696*c2c66affSColin Finck }else {
1697*c2c66affSColin Finck FIXME("Unsupported cmd %d of group %s\n", nCmdID, debugstr_guid(pguidCmdGroup));
1698*c2c66affSColin Finck }
1699*c2c66affSColin Finck
1700*c2c66affSColin Finck return E_NOTIMPL;
1701*c2c66affSColin Finck }
1702*c2c66affSColin Finck
1703*c2c66affSColin Finck static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
1704*c2c66affSColin Finck RangeCommandTarget_QueryInterface,
1705*c2c66affSColin Finck RangeCommandTarget_AddRef,
1706*c2c66affSColin Finck RangeCommandTarget_Release,
1707*c2c66affSColin Finck RangeCommandTarget_QueryStatus,
1708*c2c66affSColin Finck RangeCommandTarget_Exec
1709*c2c66affSColin Finck };
1710*c2c66affSColin Finck
1711*c2c66affSColin Finck static const tid_t HTMLTxtRange_iface_tids[] = {
1712*c2c66affSColin Finck IHTMLTxtRange_tid,
1713*c2c66affSColin Finck 0
1714*c2c66affSColin Finck };
1715*c2c66affSColin Finck static dispex_static_data_t HTMLTxtRange_dispex = {
1716*c2c66affSColin Finck NULL,
1717*c2c66affSColin Finck IHTMLTxtRange_tid,
1718*c2c66affSColin Finck NULL,
1719*c2c66affSColin Finck HTMLTxtRange_iface_tids
1720*c2c66affSColin Finck };
1721*c2c66affSColin Finck
HTMLTxtRange_Create(HTMLDocumentNode * doc,nsIDOMRange * nsrange,IHTMLTxtRange ** p)1722*c2c66affSColin Finck HRESULT HTMLTxtRange_Create(HTMLDocumentNode *doc, nsIDOMRange *nsrange, IHTMLTxtRange **p)
1723*c2c66affSColin Finck {
1724*c2c66affSColin Finck HTMLTxtRange *ret;
1725*c2c66affSColin Finck
1726*c2c66affSColin Finck ret = heap_alloc(sizeof(HTMLTxtRange));
1727*c2c66affSColin Finck if(!ret)
1728*c2c66affSColin Finck return E_OUTOFMEMORY;
1729*c2c66affSColin Finck
1730*c2c66affSColin Finck init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLTxtRange_iface, &HTMLTxtRange_dispex);
1731*c2c66affSColin Finck
1732*c2c66affSColin Finck ret->IHTMLTxtRange_iface.lpVtbl = &HTMLTxtRangeVtbl;
1733*c2c66affSColin Finck ret->IOleCommandTarget_iface.lpVtbl = &OleCommandTargetVtbl;
1734*c2c66affSColin Finck ret->ref = 1;
1735*c2c66affSColin Finck
1736*c2c66affSColin Finck if(nsrange)
1737*c2c66affSColin Finck nsIDOMRange_AddRef(nsrange);
1738*c2c66affSColin Finck ret->nsrange = nsrange;
1739*c2c66affSColin Finck
1740*c2c66affSColin Finck ret->doc = doc;
1741*c2c66affSColin Finck list_add_head(&doc->range_list, &ret->entry);
1742*c2c66affSColin Finck
1743*c2c66affSColin Finck *p = &ret->IHTMLTxtRange_iface;
1744*c2c66affSColin Finck return S_OK;
1745*c2c66affSColin Finck }
1746*c2c66affSColin Finck
detach_ranges(HTMLDocumentNode * This)1747*c2c66affSColin Finck void detach_ranges(HTMLDocumentNode *This)
1748*c2c66affSColin Finck {
1749*c2c66affSColin Finck HTMLTxtRange *iter;
1750*c2c66affSColin Finck
1751*c2c66affSColin Finck LIST_FOR_EACH_ENTRY(iter, &This->range_list, HTMLTxtRange, entry) {
1752*c2c66affSColin Finck iter->doc = NULL;
1753*c2c66affSColin Finck }
1754*c2c66affSColin Finck }
1755