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);