2 * Copyright 2006 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
35 #include "mshtml_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
39 #define DOM_VK_LEFT VK_LEFT
40 #define DOM_VK_UP VK_UP
41 #define DOM_VK_RIGHT VK_RIGHT
42 #define DOM_VK_DOWN VK_DOWN
44 static const WCHAR wszFont
[] = {'f','o','n','t',0};
45 static const WCHAR wszSize
[] = {'s','i','z','e',0};
47 static nsISelection
*get_ns_selection(HTMLDocument
*This
)
49 nsIDOMWindow
*dom_window
;
50 nsISelection
*nsselection
= NULL
;
53 if(!This
->nscontainer
)
56 nsres
= nsIWebBrowser_GetContentDOMWindow(This
->nscontainer
->webbrowser
, &dom_window
);
60 nsIDOMWindow_GetSelection(dom_window
, &nsselection
);
61 nsIDOMWindow_Release(dom_window
);
67 static void remove_child_attr(nsIDOMElement
*elem
, LPCWSTR tag
, nsAString
*attr_str
)
70 PRUint32 child_cnt
, i
;
71 nsIDOMNode
*child_node
;
72 nsIDOMNodeList
*node_list
;
75 nsIDOMElement_HasChildNodes(elem
, &has_children
);
79 nsIDOMElement_GetChildNodes(elem
, &node_list
);
80 nsIDOMNodeList_GetLength(node_list
, &child_cnt
);
82 for(i
=0; i
<child_cnt
; i
++) {
83 nsIDOMNodeList_Item(node_list
, i
, &child_node
);
85 nsIDOMNode_GetNodeType(child_node
, &node_type
);
86 if(node_type
== ELEMENT_NODE
) {
87 nsIDOMElement
*child_elem
;
89 const PRUnichar
*ctag
;
91 nsIDOMNode_QueryInterface(child_node
, &IID_nsIDOMElement
, (void**)&child_elem
);
93 nsAString_Init(&tag_str
, NULL
);
94 nsIDOMElement_GetTagName(child_elem
, &tag_str
);
95 nsAString_GetData(&tag_str
, &ctag
, NULL
);
97 if(!strcmpiW(ctag
, tag
))
98 /* FIXME: remove node if there are no more attributes */
99 nsIDOMElement_RemoveAttribute(child_elem
, attr_str
);
101 nsAString_Finish(&tag_str
);
103 remove_child_attr(child_elem
, tag
, attr_str
);
105 nsIDOMNode_Release(child_elem
);
108 nsIDOMNode_Release(child_node
);
111 nsIDOMNodeList_Release(node_list
);
114 void get_font_size(HTMLDocument
*This
, WCHAR
*ret
)
116 nsISelection
*nsselection
= get_ns_selection(This
);
117 nsIDOMElement
*elem
= NULL
;
118 nsIDOMNode
*node
= NULL
, *tmp_node
;
129 nsISelection_GetFocusNode(nsselection
, &node
);
130 nsISelection_Release(nsselection
);
133 nsres
= nsIDOMNode_GetNodeType(node
, &node_type
);
134 if(NS_FAILED(nsres
) || node_type
== DOCUMENT_NODE
)
137 if(node_type
== ELEMENT_NODE
) {
138 nsIDOMNode_QueryInterface(node
, &IID_nsIDOMElement
, (void**)&elem
);
140 nsAString_Init(&tag_str
, NULL
);
141 nsIDOMElement_GetTagName(elem
, &tag_str
);
142 nsAString_GetData(&tag_str
, &tag
, NULL
);
144 if(!strcmpiW(tag
, wszFont
)) {
145 nsAString size_str
, val_str
;
148 TRACE("found font tag %p\n", elem
);
150 nsAString_Init(&size_str
, wszSize
);
151 nsAString_Init(&val_str
, NULL
);
153 nsIDOMElement_GetAttribute(elem
, &size_str
, &val_str
);
154 nsAString_GetData(&val_str
, &val
, NULL
);
157 TRACE("found size %s\n", debugstr_w(val
));
161 nsAString_Finish(&size_str
);
162 nsAString_Finish(&val_str
);
165 nsAString_Finish(&tag_str
);
167 nsIDOMElement_Release(elem
);
174 nsIDOMNode_GetParentNode(node
, &node
);
175 nsIDOMNode_Release(tmp_node
);
179 nsIDOMNode_Release(node
);
182 void set_font_size(HTMLDocument
*This
, LPCWSTR size
)
184 nsISelection
*nsselection
;
186 nsIDOMDocument
*nsdoc
;
189 PRInt32 range_cnt
= 0;
195 nsselection
= get_ns_selection(This
);
200 nsres
= nsIWebNavigation_GetDocument(This
->nscontainer
->navigation
, &nsdoc
);
204 nsAString_Init(&font_str
, wszFont
);
205 nsAString_Init(&size_str
, wszSize
);
206 nsAString_Init(&val_str
, size
);
208 nsISelection_GetRangeCount(nsselection
, &range_cnt
);
210 FIXME("range_cnt %d not supprted\n", range_cnt
);
212 nsIDOMDocument_CreateElement(nsdoc
, &font_str
, &elem
);
213 nsIDOMElement_SetAttribute(elem
, &size_str
, &val_str
);
215 nsISelection_GetRangeAt(nsselection
, 0, &range
);
216 nsISelection_GetIsCollapsed(nsselection
, &collapsed
);
217 nsISelection_RemoveAllRanges(nsselection
);
219 nsIDOMRange_SurroundContents(range
, (nsIDOMNode
*)elem
);
222 nsISelection_Collapse(nsselection
, (nsIDOMNode
*)elem
, 0);
224 /* Remove all size attrbutes from the range */
225 remove_child_attr(elem
, wszFont
, &size_str
);
226 nsISelection_SelectAllChildren(nsselection
, (nsIDOMNode
*)elem
);
229 nsIDOMRange_Release(range
);
230 nsIDOMElement_Release(elem
);
232 nsAString_Finish(&font_str
);
233 nsAString_Finish(&size_str
);
234 nsAString_Finish(&val_str
);
236 nsISelection_Release(nsselection
);
237 nsIDOMDocument_Release(nsdoc
);
240 static BOOL
is_visible_text_node(nsIDOMNode
*node
)
242 nsIDOMCharacterData
*char_data
;
247 nsIDOMNode_QueryInterface(node
, &IID_nsIDOMCharacterData
, (void**)&char_data
);
249 nsIDOMCharacterData_GetLength(char_data
, &len
);
251 nsAString_Init(&data_str
, NULL
);
252 nsIDOMCharacterData_GetData(char_data
, &data_str
);
253 nsAString_GetData(&data_str
, &data
, NULL
);
257 for(ptr
=data
+1; ptr
&& isspaceW(*ptr
); ptr
++)
261 nsAString_Finish(&data_str
);
263 nsIDOMCharacterData_Release(char_data
);
268 static nsIDOMNode
*get_child_text_node(nsIDOMNode
*node
, BOOL first
)
270 nsIDOMNode
*iter
, *iter2
;
273 nsIDOMNode_GetFirstChild(node
, &iter
);
275 nsIDOMNode_GetLastChild(node
, &iter
);
280 nsIDOMNode_GetNodeType(iter
, &node_type
);
283 if(is_visible_text_node(iter
))
286 iter2
= get_child_text_node(iter
, first
);
288 nsIDOMNode_Release(iter
);
294 nsIDOMNode_GetNextSibling(iter
, &iter2
);
296 nsIDOMNode_GetPreviousSibling(iter
, &iter2
);
298 nsIDOMNode_Release(iter
);
305 static nsIDOMNode
*get_next_text_node(nsIDOMNode
*node
, BOOL next
)
307 nsIDOMNode
*iter
, *iter2
= NULL
, *parent
= NULL
;
311 nsIDOMNode_AddRef(iter
);
315 nsIDOMNode_GetNextSibling(iter
, &iter2
);
317 nsIDOMNode_GetPreviousSibling(iter
, &iter2
);
320 nsIDOMNode_GetParentNode(iter
, &parent
);
321 nsIDOMNode_Release(iter
);
328 nsIDOMNode_GetNextSibling(iter
, &iter2
);
330 nsIDOMNode_GetPreviousSibling(iter
, &iter2
);
333 nsIDOMNode_Release(iter
);
336 nsIDOMNode_GetNodeType(iter
, &node_type
);
340 if(is_visible_text_node(iter
))
343 iter2
= get_child_text_node(iter
, next
);
345 nsIDOMNode_Release(iter
);
354 static void collapse_end_node(nsISelection
*selection
, nsIDOMNode
*node
)
356 nsIDOMCharacterData
*char_data
;
359 nsIDOMNode_QueryInterface(node
, &IID_nsIDOMCharacterData
, (void**)&char_data
);
360 nsIDOMCharacterData_GetLength(char_data
, &len
);
361 nsIDOMCharacterData_Release(char_data
);
363 nsISelection_Collapse(selection
, node
, len
);
366 static void collapse_next_char(HTMLDocument
*doc
, nsIDOMKeyEvent
*event
, BOOL next
)
368 nsISelection
*selection
= get_ns_selection(doc
);
372 nsIDOMNode
*text_node
;
374 nsIDOMKeyEvent_GetCtrlKey(event
, &b
);
377 nsIDOMKeyEvent_GetShiftKey(event
, &b
);
380 nsISelection_GetIsCollapsed(selection
, &collapsed
);
382 nsISelection_CollapseToEnd(selection
);
384 nsISelection_GetFocusNode(selection
, &node
);
385 nsIDOMNode_GetNodeType(node
, &node_type
);
387 if(node_type
== TEXT_NODE
) {
388 nsIDOMCharacterData
*char_data
;
392 nsISelection_GetFocusOffset(selection
, &offset
);
394 nsIDOMNode_QueryInterface(node
, &IID_nsIDOMCharacterData
, (void**)&char_data
);
395 nsIDOMCharacterData_GetLength(char_data
, &len
);
396 nsIDOMCharacterData_Release(char_data
);
398 if(next
? offset
!= len
: offset
) {
399 nsISelection_Collapse(selection
, node
, offset
+ (next
?1:-1));
404 text_node
= get_next_text_node(node
, next
);
407 nsISelection_Collapse(selection
, text_node
, 1);
409 collapse_end_node(selection
, text_node
);
410 nsIDOMNode_Release(text_node
);
413 nsIDOMNode_Release(node
);
414 nsISelection_Release(selection
);
417 void handle_edit_event(HTMLDocument
*This
, nsIDOMEvent
*event
)
419 nsIDOMKeyEvent
*key_event
;
422 nsIDOMEvent_QueryInterface(event
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
424 nsIDOMKeyEvent_GetKeyCode(key_event
, &code
);
429 collapse_next_char(This
, key_event
, FALSE
);
433 collapse_next_char(This
, key_event
, TRUE
);
436 nsIDOMKeyEvent_Release(key_event
);