xref: /reactos/dll/win32/mshtml/txtrange.c (revision c2c66aff)
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