2 * Copyright 2006-2007 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/debug.h"
33 #include "mshtml_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
38 #define NSCMD_ALIGN "cmd_align"
39 #define NSCMD_BEGINLINE "cmd_beginLine"
40 #define NSCMD_BOLD "cmd_bold"
41 #define NSCMD_CHARNEXT "cmd_charNext"
42 #define NSCMD_CHARPREVIOUS "cmd_charPrevious"
43 #define NSCMD_COPY "cmd_copy"
44 #define NSCMD_CUT "cmd_cut"
45 #define NSCMD_DELETECHARFORWARD "cmd_deleteCharForward"
46 #define NSCMD_DELETEWORDFORWARD "cmd_deleteWordForward"
47 #define NSCMD_ENDLINE "cmd_endLine"
48 #define NSCMD_FONTCOLOR "cmd_fontColor"
49 #define NSCMD_FONTFACE "cmd_fontFace"
50 #define NSCMD_INDENT "cmd_indent"
51 #define NSCMD_INSERTHR "cmd_insertHR"
52 #define NSCMD_INSERTLINKNOUI "cmd_insertLinkNoUI"
53 #define NSCMD_ITALIC "cmd_italic"
54 #define NSCMD_LINENEXT "cmd_lineNext"
55 #define NSCMD_LINEPREVIOUS "cmd_linePrevious"
56 #define NSCMD_MOVEBOTTOM "cmd_moveBottom"
57 #define NSCMD_MOVEPAGEDOWN "cmd_movePageDown"
58 #define NSCMD_MOVEPAGEUP "cmd_movePageUp"
59 #define NSCMD_MOVETOP "cmd_moveTop"
60 #define NSCMD_OL "cmd_ol"
61 #define NSCMD_OUTDENT "cmd_outdent"
62 #define NSCMD_PASTE "cmd_paste"
63 #define NSCMD_SELECTBEGINLINE "cmd_selectBeginLine"
64 #define NSCMD_SELECTBOTTOM "cmd_selectBottom"
65 #define NSCMD_SELECTCHARNEXT "cmd_selectCharNext"
66 #define NSCMD_SELECTCHARPREVIOUS "cmd_selectCharPrevious"
67 #define NSCMD_SELECTENDLINE "cmd_selectEndLine"
68 #define NSCMD_SELECTLINENEXT "cmd_selectLineNext"
69 #define NSCMD_SELECTLINEPREVIOUS "cmd_selectLinePrevious"
70 #define NSCMD_SELECTPAGEDOWN "cmd_selectPageDown"
71 #define NSCMD_SELECTPAGEUP "cmd_selectPageUp"
72 #define NSCMD_SELECTTOP "cmd_selectTop"
73 #define NSCMD_SELECTWORDNEXT "cmd_selectWordNext"
74 #define NSCMD_SELECTWORDPREVIOUS "cmd_selectWordPrevious"
75 #define NSCMD_UL "cmd_ul"
76 #define NSCMD_UNDERLINE "cmd_underline"
77 #define NSCMD_WORDNEXT "cmd_wordNext"
78 #define NSCMD_WORDPREVIOUS "cmd_wordPrevious"
80 #define NSSTATE_ATTRIBUTE "state_attribute"
81 #define NSSTATE_ALL "state_all"
83 #define NSALIGN_CENTER "center"
84 #define NSALIGN_LEFT "left"
85 #define NSALIGN_RIGHT "right"
87 #define DOM_VK_LEFT VK_LEFT
88 #define DOM_VK_UP VK_UP
89 #define DOM_VK_RIGHT VK_RIGHT
90 #define DOM_VK_DOWN VK_DOWN
91 #define DOM_VK_DELETE VK_DELETE
92 #define DOM_VK_HOME VK_HOME
93 #define DOM_VK_END VK_END
95 void set_dirty(GeckoBrowser
*browser
, VARIANT_BOOL dirty
)
99 if(browser
->usermode
!= EDITMODE
|| !browser
->editor
)
103 nsres
= nsIEditor_IncrementModificationCount(browser
->editor
, 1);
105 ERR("IncrementModificationCount failed: %08x\n", nsres
);
107 nsres
= nsIEditor_ResetModificationCount(browser
->editor
);
109 ERR("ResetModificationCount failed: %08x\n", nsres
);
113 static void do_ns_editor_command(GeckoBrowser
*This
, const char *cmd
)
117 if(!This
->editor_controller
)
120 nsres
= nsIController_DoCommand(This
->editor_controller
, cmd
);
122 ERR("DoCommand(%s) failed: %08x\n", debugstr_a(cmd
), nsres
);
125 static nsresult
get_ns_command_state(GeckoBrowser
*This
, const char *cmd
, nsICommandParams
*nsparam
)
127 nsICommandManager
*cmdmgr
;
130 nsres
= get_nsinterface((nsISupports
*)This
->webbrowser
, &IID_nsICommandManager
, (void**)&cmdmgr
);
131 if(NS_FAILED(nsres
)) {
132 ERR("Could not get nsICommandManager: %08x\n", nsres
);
136 nsres
= nsICommandManager_GetCommandState(cmdmgr
, cmd
, This
->doc
->basedoc
.window
->window_proxy
, nsparam
);
138 ERR("GetCommandState(%s) failed: %08x\n", debugstr_a(cmd
), nsres
);
140 nsICommandManager_Release(cmdmgr
);
144 static DWORD
query_ns_edit_status(HTMLDocumentNode
*doc
, const char *nscmd
)
146 nsICommandParams
*nsparam
;
149 if(doc
->browser
->usermode
!= EDITMODE
|| doc
->basedoc
.window
->readystate
< READYSTATE_INTERACTIVE
)
150 return OLECMDF_SUPPORTED
;
153 nsparam
= create_nscommand_params();
154 get_ns_command_state(doc
->browser
, nscmd
, nsparam
);
156 nsICommandParams_GetBooleanValue(nsparam
, NSSTATE_ALL
, &b
);
158 nsICommandParams_Release(nsparam
);
161 return OLECMDF_SUPPORTED
| OLECMDF_ENABLED
| (b
? OLECMDF_LATCHED
: 0);
164 static void set_ns_align(HTMLDocumentNode
*doc
, const char *align_str
)
166 nsICommandParams
*nsparam
;
168 nsparam
= create_nscommand_params();
169 nsICommandParams_SetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, align_str
);
171 do_ns_command(doc
, NSCMD_ALIGN
, nsparam
);
173 nsICommandParams_Release(nsparam
);
176 static DWORD
query_align_status(HTMLDocumentNode
*doc
, const WCHAR
*align
)
178 DWORD ret
= OLECMDF_SUPPORTED
| OLECMDF_ENABLED
;
179 nsAString justify_str
;
183 if(doc
->browser
->usermode
!= EDITMODE
|| doc
->basedoc
.window
->readystate
< READYSTATE_INTERACTIVE
)
184 return OLECMDF_SUPPORTED
;
186 nsAString_Init(&justify_str
, align
);
187 nsres
= nsIDOMHTMLDocument_QueryCommandState(doc
->nsdoc
, &justify_str
, &b
);
188 nsAString_Finish(&justify_str
);
189 if(NS_SUCCEEDED(nsres
) && b
)
190 ret
|= OLECMDF_LATCHED
;
196 static nsISelection
*get_ns_selection(HTMLDocumentNode
*doc
)
198 nsISelection
*nsselection
= NULL
;
201 nsres
= nsIDOMWindow_GetSelection(doc
->basedoc
.window
->nswindow
, &nsselection
);
203 ERR("GetSelection failed %08x\n", nsres
);
209 static void remove_child_attr(nsIDOMElement
*elem
, LPCWSTR tag
, nsAString
*attr_str
)
211 cpp_bool has_children
;
213 nsIDOMNode
*child_node
;
214 nsIDOMNodeList
*node_list
;
217 nsIDOMElement_HasChildNodes(elem
, &has_children
);
221 nsIDOMElement_GetChildNodes(elem
, &node_list
);
222 nsIDOMNodeList_GetLength(node_list
, &child_cnt
);
224 for(i
=0; i
<child_cnt
; i
++) {
225 nsIDOMNodeList_Item(node_list
, i
, &child_node
);
227 nsIDOMNode_GetNodeType(child_node
, &node_type
);
228 if(node_type
== ELEMENT_NODE
) {
229 nsIDOMElement
*child_elem
;
231 const PRUnichar
*ctag
;
233 nsIDOMNode_QueryInterface(child_node
, &IID_nsIDOMElement
, (void**)&child_elem
);
235 nsAString_Init(&tag_str
, NULL
);
236 nsIDOMElement_GetTagName(child_elem
, &tag_str
);
237 nsAString_GetData(&tag_str
, &ctag
);
239 if(!wcsicmp(ctag
, tag
))
240 /* FIXME: remove node if there are no more attributes */
241 nsIDOMElement_RemoveAttribute(child_elem
, attr_str
);
243 nsAString_Finish(&tag_str
);
245 remove_child_attr(child_elem
, tag
, attr_str
);
247 nsIDOMElement_Release(child_elem
);
250 nsIDOMNode_Release(child_node
);
253 nsIDOMNodeList_Release(node_list
);
256 static void get_font_size(HTMLDocumentNode
*doc
, WCHAR
*ret
)
258 nsISelection
*nsselection
= get_ns_selection(doc
);
259 nsIDOMElement
*elem
= NULL
;
260 nsIDOMNode
*node
= NULL
, *tmp_node
;
271 nsISelection_GetFocusNode(nsselection
, &node
);
272 nsISelection_Release(nsselection
);
275 nsres
= nsIDOMNode_GetNodeType(node
, &node_type
);
276 if(NS_FAILED(nsres
) || node_type
== DOCUMENT_NODE
)
279 if(node_type
== ELEMENT_NODE
) {
280 nsIDOMNode_QueryInterface(node
, &IID_nsIDOMElement
, (void**)&elem
);
282 nsAString_Init(&tag_str
, NULL
);
283 nsIDOMElement_GetTagName(elem
, &tag_str
);
284 nsAString_GetData(&tag_str
, &tag
);
286 if(!wcsicmp(tag
, L
"font")) {
288 const PRUnichar
*val
;
290 TRACE("found font tag %p\n", elem
);
292 get_elem_attr_value(elem
, L
"size", &val_str
, &val
);
294 TRACE("found size %s\n", debugstr_w(val
));
298 nsAString_Finish(&val_str
);
301 nsAString_Finish(&tag_str
);
302 nsIDOMElement_Release(elem
);
309 nsIDOMNode_GetParentNode(node
, &node
);
310 nsIDOMNode_Release(tmp_node
);
314 nsIDOMNode_Release(node
);
317 static void set_font_size(HTMLDocumentNode
*doc
, LPCWSTR size
)
319 nsISelection
*nsselection
;
327 nsselection
= get_ns_selection(doc
);
331 nsISelection_GetRangeCount(nsselection
, &range_cnt
);
333 FIXME("range_cnt %d not supprted\n", range_cnt
);
335 nsISelection_Release(nsselection
);
340 create_nselem(doc
, L
"font", &elem
);
342 nsAString_InitDepend(&size_str
, L
"size");
343 nsAString_InitDepend(&val_str
, size
);
345 nsIDOMElement_SetAttribute(elem
, &size_str
, &val_str
);
346 nsAString_Finish(&val_str
);
348 nsISelection_GetRangeAt(nsselection
, 0, &range
);
349 nsISelection_GetIsCollapsed(nsselection
, &collapsed
);
350 nsISelection_RemoveAllRanges(nsselection
);
352 nsIDOMRange_SurroundContents(range
, (nsIDOMNode
*)elem
);
355 nsISelection_Collapse(nsselection
, (nsIDOMNode
*)elem
, 0);
357 /* Remove all size attributes from the range */
358 remove_child_attr(elem
, L
"font", &size_str
);
359 nsISelection_SelectAllChildren(nsselection
, (nsIDOMNode
*)elem
);
362 nsISelection_Release(nsselection
);
363 nsIDOMRange_Release(range
);
364 nsIDOMElement_Release(elem
);
366 nsAString_Finish(&size_str
);
368 set_dirty(doc
->browser
, VARIANT_TRUE
);
371 static void handle_arrow_key(HTMLDocumentNode
*doc
, nsIDOMEvent
*event
, nsIDOMKeyEvent
*key_event
, const char * const cmds
[4])
376 nsIDOMKeyEvent_GetCtrlKey(key_event
, &b
);
380 nsIDOMKeyEvent_GetShiftKey(key_event
, &b
);
385 do_ns_editor_command(doc
->browser
, cmds
[i
]);
387 nsIDOMEvent_PreventDefault(event
);
390 void handle_edit_event(HTMLDocumentNode
*doc
, nsIDOMEvent
*event
)
392 nsIDOMKeyEvent
*key_event
;
395 nsIDOMEvent_QueryInterface(event
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
397 nsIDOMKeyEvent_GetKeyCode(key_event
, &code
);
401 static const char * const cmds
[] = {
404 NSCMD_SELECTCHARPREVIOUS
,
405 NSCMD_SELECTWORDPREVIOUS
409 handle_arrow_key(doc
, event
, key_event
, cmds
);
413 static const char * const cmds
[] = {
416 NSCMD_SELECTCHARNEXT
,
421 handle_arrow_key(doc
, event
, key_event
, cmds
);
425 static const char * const cmds
[] = {
428 NSCMD_SELECTLINEPREVIOUS
,
433 handle_arrow_key(doc
, event
, key_event
, cmds
);
437 static const char * const cmds
[] = {
440 NSCMD_SELECTLINENEXT
,
445 handle_arrow_key(doc
, event
, key_event
, cmds
);
448 case DOM_VK_DELETE
: {
449 static const char * const cmds
[] = {
450 NSCMD_DELETECHARFORWARD
,
451 NSCMD_DELETEWORDFORWARD
,
456 handle_arrow_key(doc
, event
, key_event
, cmds
);
460 static const char * const cmds
[] = {
463 NSCMD_SELECTBEGINLINE
,
468 handle_arrow_key(doc
, event
, key_event
, cmds
);
472 static const char * const cmds
[] = {
480 handle_arrow_key(doc
, event
, key_event
, cmds
);
485 nsIDOMKeyEvent_Release(key_event
);
488 static void set_ns_fontname(HTMLDocumentNode
*doc
, const char *fontname
)
490 nsICommandParams
*nsparam
= create_nscommand_params();
492 nsICommandParams_SetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, fontname
);
493 do_ns_command(doc
, NSCMD_FONTFACE
, nsparam
);
494 nsICommandParams_Release(nsparam
);
497 static HRESULT
exec_delete(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
499 TRACE("(%p)->(%p %p)\n", doc
, in
, out
);
501 do_ns_editor_command(doc
->browser
, NSCMD_DELETECHARFORWARD
);
503 update_doc(doc
->browser
->doc
, UPDATE_UI
);
507 static HRESULT
exec_fontname(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
509 TRACE("(%p)->(%p %p)\n", doc
, in
, out
);
514 if(V_VT(in
) != VT_BSTR
) {
515 FIXME("Unsupported fontname %s\n", debugstr_variant(out
));
519 TRACE("%s\n", debugstr_w(V_BSTR(in
)));
521 stra
= heap_strdupWtoA(V_BSTR(in
));
522 set_ns_fontname(doc
, stra
);
525 update_doc(doc
->browser
->doc
, UPDATE_UI
);
529 nsICommandParams
*nsparam
;
538 nsparam
= create_nscommand_params();
540 nsres
= get_ns_command_state(doc
->browser
, NSCMD_FONTFACE
, nsparam
);
544 nsICommandParams_GetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, &stra
);
545 nsICommandParams_Release(nsparam
);
547 len
= MultiByteToWideChar(CP_ACP
, 0, stra
, -1, NULL
, 0);
548 strw
= heap_alloc(len
*sizeof(WCHAR
));
549 MultiByteToWideChar(CP_ACP
, 0, stra
, -1, strw
, len
);
552 V_BSTR(out
) = SysAllocString(strw
);
559 static HRESULT
exec_forecolor(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
561 TRACE("(%p)->(%p %p)\n", doc
, in
, out
);
564 if(V_VT(in
) == VT_I4
) {
565 nsICommandParams
*nsparam
= create_nscommand_params();
568 sprintf(color_str
, "#%02x%02x%02x",
569 V_I4(in
)&0xff, (V_I4(in
)>>8)&0xff, (V_I4(in
)>>16)&0xff);
571 nsICommandParams_SetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, color_str
);
572 do_ns_command(doc
, NSCMD_FONTCOLOR
, nsparam
);
574 nsICommandParams_Release(nsparam
);
576 FIXME("unsupported forecolor %s\n", debugstr_variant(in
));
579 update_doc(doc
->browser
->doc
, UPDATE_UI
);
583 FIXME("unsupported out\n");
590 static HRESULT
exec_fontsize(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
592 TRACE("(%p)->(%p %p)\n", doc
, in
, out
);
597 get_font_size(doc
, val
);
599 V_I4(out
) = wcstol(val
, NULL
, 10);
606 wsprintfW(size
, L
"%d", V_I4(in
));
607 set_font_size(doc
, size
);
611 set_font_size(doc
, V_BSTR(in
));
614 FIXME("unsupported fontsize %s\n", debugstr_variant(in
));
617 update_doc(doc
->browser
->doc
, UPDATE_UI
);
623 static HRESULT
exec_font(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
626 FIXME("(%p)->(%p %p)\n", doc
, in
, out
);
630 static HRESULT
exec_bold(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
632 TRACE("(%p)\n", doc
);
635 FIXME("unsupported args\n");
637 do_ns_command(doc
, NSCMD_BOLD
, NULL
);
638 update_doc(doc
->browser
->doc
, UPDATE_UI
);
642 static HRESULT
exec_italic(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
644 TRACE("(%p)\n", doc
);
647 FIXME("unsupported args\n");
649 do_ns_command(doc
, NSCMD_ITALIC
, NULL
);
650 update_doc(doc
->browser
->doc
, UPDATE_UI
);
654 static HRESULT
query_justify(HTMLDocumentNode
*doc
, OLECMD
*cmd
)
657 case IDM_JUSTIFYCENTER
:
658 TRACE("(%p) IDM_JUSTIFYCENTER\n", doc
);
659 cmd
->cmdf
= query_align_status(doc
, L
"justifycenter");
661 case IDM_JUSTIFYLEFT
:
662 TRACE("(%p) IDM_JUSTIFYLEFT\n", doc
);
663 /* FIXME: We should set OLECMDF_LATCHED only if it's set explicitly. */
664 if(doc
->browser
->usermode
!= EDITMODE
|| doc
->basedoc
.window
->readystate
< READYSTATE_INTERACTIVE
)
665 cmd
->cmdf
= OLECMDF_SUPPORTED
;
667 cmd
->cmdf
= OLECMDF_SUPPORTED
| OLECMDF_ENABLED
;
669 case IDM_JUSTIFYRIGHT
:
670 TRACE("(%p) IDM_JUSTIFYRIGHT\n", doc
);
671 cmd
->cmdf
= query_align_status(doc
, L
"justifyright");
678 static HRESULT
exec_justifycenter(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
680 TRACE("(%p)\n", doc
);
683 FIXME("unsupported args\n");
685 set_ns_align(doc
, NSALIGN_CENTER
);
686 update_doc(doc
->browser
->doc
, UPDATE_UI
);
690 static HRESULT
exec_justifyleft(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
692 TRACE("(%p)\n", doc
);
695 FIXME("unsupported args\n");
697 set_ns_align(doc
, NSALIGN_LEFT
);
698 update_doc(doc
->browser
->doc
, UPDATE_UI
);
702 static HRESULT
exec_justifyright(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
704 TRACE("(%p)\n", doc
);
707 FIXME("unsupported args\n");
709 set_ns_align(doc
, NSALIGN_RIGHT
);
710 update_doc(doc
->browser
->doc
, UPDATE_UI
);
714 static HRESULT
exec_underline(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
716 TRACE("(%p)\n", doc
);
719 FIXME("unsupported args\n");
721 do_ns_command(doc
, NSCMD_UNDERLINE
, NULL
);
722 update_doc(doc
->browser
->doc
, UPDATE_UI
);
726 static HRESULT
exec_horizontalline(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
728 TRACE("(%p)\n", doc
);
731 FIXME("unsupported args\n");
733 do_ns_command(doc
, NSCMD_INSERTHR
, NULL
);
734 update_doc(doc
->browser
->doc
, UPDATE_UI
);
738 static HRESULT
exec_orderlist(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
740 TRACE("(%p)\n", doc
);
743 FIXME("unsupported args\n");
745 do_ns_command(doc
, NSCMD_OL
, NULL
);
746 update_doc(doc
->browser
->doc
, UPDATE_UI
);
750 static HRESULT
exec_unorderlist(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
752 TRACE("(%p)\n", doc
);
755 FIXME("unsupported args\n");
757 do_ns_command(doc
, NSCMD_UL
, NULL
);
758 update_doc(doc
->browser
->doc
, UPDATE_UI
);
762 static HRESULT
exec_indent(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
764 TRACE("(%p)\n", doc
);
767 FIXME("unsupported args\n");
769 do_ns_command(doc
, NSCMD_INDENT
, NULL
);
770 update_doc(doc
->browser
->doc
, UPDATE_UI
);
774 static HRESULT
exec_outdent(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
776 TRACE("(%p)\n", doc
);
779 FIXME("unsupported args\n");
781 do_ns_command(doc
, NSCMD_OUTDENT
, NULL
);
782 update_doc(doc
->browser
->doc
, UPDATE_UI
);
786 static HRESULT
exec_composesettings(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
790 if(out
|| !in
|| V_VT(in
) != VT_BSTR
) {
791 WARN("invalid arg %s\n", debugstr_variant(in
));
795 TRACE("(%p)->(%x %s)\n", doc
, cmdexecopt
, debugstr_w(V_BSTR(in
)));
797 update_doc(doc
->browser
->doc
, UPDATE_UI
);
801 exec_bold(doc
, cmdexecopt
, NULL
, NULL
);
802 ptr
= wcschr(ptr
, ',');
807 exec_italic(doc
, cmdexecopt
, NULL
, NULL
);
808 ptr
= wcschr(ptr
, ',');
813 exec_underline(doc
, cmdexecopt
, NULL
, NULL
);
814 ptr
= wcschr(ptr
, ',');
818 if(is_digit(*++ptr
)) {
824 exec_fontsize(doc
, cmdexecopt
, &v
, NULL
);
826 ptr
= wcschr(ptr
, ',');
831 FIXME("set font color\n");
832 ptr
= wcschr(ptr
, ',');
837 FIXME("set background color\n");
838 ptr
= wcschr(ptr
, ',');
847 V_BSTR(&v
) = SysAllocString(ptr
);
849 exec_fontname(doc
, cmdexecopt
, &v
, NULL
);
851 SysFreeString(V_BSTR(&v
));
857 HRESULT
editor_exec_copy(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
859 update_doc(doc
->browser
->doc
, UPDATE_UI
);
860 do_ns_editor_command(doc
->browser
, NSCMD_COPY
);
864 HRESULT
editor_exec_cut(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
866 update_doc(doc
->browser
->doc
, UPDATE_UI
);
867 do_ns_editor_command(doc
->browser
, NSCMD_CUT
);
871 HRESULT
editor_exec_paste(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
873 update_doc(doc
->browser
->doc
, UPDATE_UI
);
874 do_ns_editor_command(doc
->browser
, NSCMD_PASTE
);
878 static HRESULT
exec_setdirty(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
880 TRACE("(%p)->(%08x %p %p)\n", doc
, cmdexecopt
, in
, out
);
885 if(V_VT(in
) == VT_BOOL
)
886 set_dirty(doc
->browser
, V_BOOL(in
));
888 FIXME("unsupported arg %s\n", debugstr_variant(in
));
893 static HRESULT
query_edit_status(HTMLDocumentNode
*doc
, OLECMD
*cmd
)
897 TRACE("CGID_MSHTML: IDM_DELETE\n");
898 cmd
->cmdf
= query_ns_edit_status(doc
, NULL
);
901 TRACE("CGID_MSHTML: IDM_FONTNAME\n");
902 cmd
->cmdf
= query_ns_edit_status(doc
, NULL
);
905 TRACE("CGID_MSHTML: IDM_FONTSIZE\n");
906 cmd
->cmdf
= query_ns_edit_status(doc
, NULL
);
909 TRACE("CGID_MSHTML: IDM_BOLD\n");
910 cmd
->cmdf
= query_ns_edit_status(doc
, NSCMD_BOLD
);
913 TRACE("CGID_MSHTML: IDM_FORECOLOR\n");
914 cmd
->cmdf
= query_ns_edit_status(doc
, NULL
);
917 TRACE("CGID_MSHTML: IDM_ITALIC\n");
918 cmd
->cmdf
= query_ns_edit_status(doc
, NSCMD_ITALIC
);
921 TRACE("CGID_MSHTML: IDM_UNDERLINE\n");
922 cmd
->cmdf
= query_ns_edit_status(doc
, NSCMD_UNDERLINE
);
924 case IDM_HORIZONTALLINE
:
925 TRACE("CGID_MSHTML: IDM_HORIZONTALLINE\n");
926 cmd
->cmdf
= query_ns_edit_status(doc
, NULL
);
929 TRACE("CGID_MSHTML: IDM_ORDERLIST\n");
930 cmd
->cmdf
= query_ns_edit_status(doc
, NSCMD_OL
);
932 case IDM_UNORDERLIST
:
933 TRACE("CGID_MSHTML: IDM_HORIZONTALLINE\n");
934 cmd
->cmdf
= query_ns_edit_status(doc
, NSCMD_UL
);
937 TRACE("CGID_MSHTML: IDM_INDENT\n");
938 cmd
->cmdf
= query_ns_edit_status(doc
, NULL
);
941 TRACE("CGID_MSHTML: IDM_OUTDENT\n");
942 cmd
->cmdf
= query_ns_edit_status(doc
, NULL
);
945 TRACE("CGID_MSHTML: IDM_HYPERLINK\n");
946 cmd
->cmdf
= query_ns_edit_status(doc
, NULL
);
953 static INT_PTR CALLBACK
hyperlink_dlgproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
960 HWND hwndCB
= GetDlgItem(hwnd
, IDC_TYPE
);
961 HWND hwndURL
= GetDlgItem(hwnd
, IDC_URL
);
964 SetWindowLongPtrW(hwnd
, DWLP_USER
, lparam
);
966 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)L
"(other)");
967 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)L
"file:");
968 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)L
"ftp:");
969 def_idx
= SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)L
"http:");
970 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)L
"https:");
971 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)L
"mailto:");
972 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)L
"news:");
973 SendMessageW(hwndCB
, CB_SETCURSEL
, def_idx
, 0);
975 /* force the updating of the URL edit box */
976 SendMessageW(hwnd
, WM_COMMAND
, MAKEWPARAM(IDC_TYPE
, CBN_SELCHANGE
), (LPARAM
)hwndCB
);
979 len
= SendMessageW(hwndURL
, WM_GETTEXTLENGTH
, 0, 0);
980 SendMessageW(hwndURL
, EM_SETSEL
, 0, len
);
987 case MAKEWPARAM(IDCANCEL
, BN_CLICKED
):
988 EndDialog(hwnd
, wparam
);
990 case MAKEWPARAM(IDOK
, BN_CLICKED
):
992 BSTR
*url
= (BSTR
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
993 HWND hwndURL
= GetDlgItem(hwnd
, IDC_URL
);
994 INT len
= GetWindowTextLengthW(hwndURL
);
995 *url
= SysAllocStringLen(NULL
, len
+ 1);
996 GetWindowTextW(hwndURL
, *url
, len
+ 1);
997 EndDialog(hwnd
, wparam
);
1000 case MAKEWPARAM(IDC_TYPE
, CBN_SELCHANGE
):
1002 HWND hwndURL
= GetDlgItem(hwnd
, IDC_URL
);
1008 static const WCHAR wszSlashSlash
[] = {'/','/'};
1010 /* get string of currently selected hyperlink type */
1011 item
= SendMessageW((HWND
)lparam
, CB_GETCURSEL
, 0, 0);
1012 len
= SendMessageW((HWND
)lparam
, CB_GETLBTEXTLEN
, item
, 0);
1013 type
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
1014 SendMessageW((HWND
)lparam
, CB_GETLBTEXT
, item
, (LPARAM
)type
);
1016 if (!wcscmp(type
, L
"(other)"))
1019 /* get current URL */
1020 len
= GetWindowTextLengthW(hwndURL
);
1021 url
= HeapAlloc(GetProcessHeap(), 0, (len
+ lstrlenW(type
) + 3) * sizeof(WCHAR
));
1022 GetWindowTextW(hwndURL
, url
, len
+ 1);
1024 /* strip off old protocol */
1025 p
= wcschr(url
, ':');
1026 if (p
&& p
[1] == '/' && p
[2] == '/')
1029 memmove(url
+ (*type
!= '\0' ? lstrlenW(type
) + 2 : 0), p
, (len
+ 1 - (p
- url
)) * sizeof(WCHAR
));
1031 /* add new protocol */
1034 memcpy(url
, type
, (lstrlenW(type
) + 1) * sizeof(WCHAR
));
1035 if (wcscmp(type
, L
"mailto:") && wcscmp(type
, L
"news:"))
1036 memcpy(url
+ lstrlenW(type
), wszSlashSlash
, sizeof(wszSlashSlash
));
1039 SetWindowTextW(hwndURL
, url
);
1041 HeapFree(GetProcessHeap(), 0, url
);
1042 HeapFree(GetProcessHeap(), 0, type
);
1048 EndDialog(hwnd
, IDCANCEL
);
1055 static HRESULT
exec_hyperlink(HTMLDocumentNode
*doc
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
1057 nsAString href_str
, ns_url
;
1058 nsIHTMLEditor
*html_editor
;
1059 nsIDOMElement
*anchor_elem
;
1060 cpp_bool insert_link_at_caret
;
1061 nsISelection
*nsselection
;
1064 HRESULT hres
= E_FAIL
;
1066 TRACE("%p, 0x%x, %p, %p\n", doc
, cmdexecopt
, in
, out
);
1068 if (cmdexecopt
== OLECMDEXECOPT_DONTPROMPTUSER
)
1070 if (!in
|| V_VT(in
) != VT_BSTR
)
1072 WARN("invalid arg\n");
1073 return E_INVALIDARG
;
1079 ret
= DialogBoxParamW(hInst
, MAKEINTRESOURCEW(IDD_HYPERLINK
), NULL
/* FIXME */, hyperlink_dlgproc
, (LPARAM
)&url
);
1081 return OLECMDERR_E_CANCELED
;
1085 WARN("NULL nsdoc\n");
1086 return E_UNEXPECTED
;
1089 nsselection
= get_ns_selection(doc
);
1093 /* create an element for the link */
1094 create_nselem(doc
, L
"a", &anchor_elem
);
1096 nsAString_InitDepend(&href_str
, L
"href");
1097 nsAString_InitDepend(&ns_url
, url
);
1098 nsIDOMElement_SetAttribute(anchor_elem
, &href_str
, &ns_url
);
1099 nsAString_Finish(&href_str
);
1101 nsISelection_GetIsCollapsed(nsselection
, &insert_link_at_caret
);
1103 /* create an element with text of URL */
1104 if (insert_link_at_caret
) {
1105 nsIDOMNode
*unused_node
;
1106 nsIDOMText
*text_node
;
1108 nsIDOMHTMLDocument_CreateTextNode(doc
->nsdoc
, &ns_url
, &text_node
);
1110 /* wrap the <a> tags around the text element */
1111 nsIDOMElement_AppendChild(anchor_elem
, (nsIDOMNode
*)text_node
, &unused_node
);
1112 nsIDOMText_Release(text_node
);
1113 nsIDOMNode_Release(unused_node
);
1116 nsAString_Finish(&ns_url
);
1118 nsIEditor_QueryInterface(doc
->browser
->editor
, &IID_nsIHTMLEditor
, (void **)&html_editor
);
1122 if (insert_link_at_caret
) {
1123 /* add them to the document at the caret position */
1124 nsres
= nsIHTMLEditor_InsertElementAtSelection(html_editor
, anchor_elem
, FALSE
);
1125 nsISelection_SelectAllChildren(nsselection
, (nsIDOMNode
*)anchor_elem
);
1126 }else /* add them around the selection using the magic provided to us by nsIHTMLEditor */
1127 nsres
= nsIHTMLEditor_InsertLinkAroundSelection(html_editor
, anchor_elem
);
1129 nsIHTMLEditor_Release(html_editor
);
1130 hres
= NS_SUCCEEDED(nsres
) ? S_OK
: E_FAIL
;
1133 nsISelection_Release(nsselection
);
1134 nsIDOMElement_Release(anchor_elem
);
1136 if (cmdexecopt
!= OLECMDEXECOPT_DONTPROMPTUSER
)
1139 TRACE("-- 0x%08x\n", hres
);
1143 const cmdtable_t editmode_cmds
[] = {
1144 {IDM_DELETE
, query_edit_status
, exec_delete
},
1145 {IDM_FONTNAME
, query_edit_status
, exec_fontname
},
1146 {IDM_FONTSIZE
, query_edit_status
, exec_fontsize
},
1147 {IDM_FORECOLOR
, query_edit_status
, exec_forecolor
},
1148 {IDM_BOLD
, query_edit_status
, exec_bold
},
1149 {IDM_ITALIC
, query_edit_status
, exec_italic
},
1150 {IDM_JUSTIFYCENTER
, query_justify
, exec_justifycenter
},
1151 {IDM_JUSTIFYRIGHT
, query_justify
, exec_justifyright
},
1152 {IDM_JUSTIFYLEFT
, query_justify
, exec_justifyleft
},
1153 {IDM_FONT
, NULL
, exec_font
},
1154 {IDM_UNDERLINE
, query_edit_status
, exec_underline
},
1155 {IDM_HORIZONTALLINE
, query_edit_status
, exec_horizontalline
},
1156 {IDM_ORDERLIST
, query_edit_status
, exec_orderlist
},
1157 {IDM_UNORDERLIST
, query_edit_status
, exec_unorderlist
},
1158 {IDM_INDENT
, query_edit_status
, exec_indent
},
1159 {IDM_OUTDENT
, query_edit_status
, exec_outdent
},
1160 {IDM_COMPOSESETTINGS
, NULL
, exec_composesettings
},
1161 {IDM_HYPERLINK
, query_edit_status
, exec_hyperlink
},
1162 {IDM_SETDIRTY
, NULL
, exec_setdirty
},
1166 void init_editor(HTMLDocumentNode
*doc
)
1168 update_doc(doc
->browser
->doc
, UPDATE_UI
);
1170 set_ns_fontname(doc
, "Times New Roman");
1173 HRESULT
browser_is_dirty(GeckoBrowser
*browser
)
1177 if(browser
->usermode
!= EDITMODE
|| !browser
->editor
)
1180 nsIEditor_GetDocumentModified(browser
->editor
, &modified
);
1181 return modified
? S_OK
: S_FALSE
;
1184 HRESULT
setup_edit_mode(HTMLDocumentObj
*doc
)
1189 if(doc
->nscontainer
->usermode
== EDITMODE
)
1192 doc
->nscontainer
->usermode
= EDITMODE
;
1194 if(doc
->basedoc
.window
->mon
) {
1195 CLSID clsid
= IID_NULL
;
1196 hres
= IMoniker_GetClassID(doc
->basedoc
.window
->mon
, &clsid
);
1197 if(SUCCEEDED(hres
)) {
1198 /* We should use IMoniker::Save here */
1199 FIXME("Use CLSID %s\n", debugstr_guid(&clsid
));
1204 IOleInPlaceFrame_SetStatusText(doc
->frame
, NULL
);
1206 doc
->basedoc
.window
->readystate
= READYSTATE_UNINITIALIZED
;
1209 IOleCommandTarget
*cmdtrg
;
1211 hres
= IOleClientSite_QueryInterface(doc
->client
, &IID_IOleCommandTarget
, (void**)&cmdtrg
);
1212 if(SUCCEEDED(hres
)) {
1217 IOleCommandTarget_Exec(cmdtrg
, &CGID_ShellDocView
, 37, 0, &var
, NULL
);
1219 IOleCommandTarget_Release(cmdtrg
);
1224 DOCHOSTUIINFO hostinfo
;
1226 memset(&hostinfo
, 0, sizeof(DOCHOSTUIINFO
));
1227 hostinfo
.cbSize
= sizeof(DOCHOSTUIINFO
);
1228 hres
= IDocHostUIHandler_GetHostInfo(doc
->hostui
, &hostinfo
);
1230 /* FIXME: use hostinfo */
1231 TRACE("hostinfo = {%u %08x %08x %s %s}\n",
1232 hostinfo
.cbSize
, hostinfo
.dwFlags
, hostinfo
.dwDoubleClick
,
1233 debugstr_w(hostinfo
.pchHostCss
), debugstr_w(hostinfo
.pchHostNS
));
1236 update_doc(doc
, UPDATE_UI
);
1238 if(doc
->basedoc
.window
->mon
) {
1239 /* FIXME: We should find nicer way to do this */
1240 remove_target_tasks(doc
->task_magic
);
1242 mon
= doc
->basedoc
.window
->mon
;
1243 IMoniker_AddRef(mon
);
1245 hres
= CreateURLMoniker(NULL
, L
"about:blank", &mon
);
1247 FIXME("CreateURLMoniker failed: %08x\n", hres
);
1252 hres
= IPersistMoniker_Load(&doc
->basedoc
.IPersistMoniker_iface
, TRUE
, mon
, NULL
, 0);
1253 IMoniker_Release(mon
);
1257 if(doc
->ui_active
) {
1259 call_set_active_object(doc
->ip_window
, NULL
);
1261 IDocHostUIHandler_HideUI(doc
->hostui
);
1264 if(doc
->ui_active
) {
1265 RECT rcBorderWidths
;
1268 IDocHostUIHandler_ShowUI(doc
->hostui
, DOCHOSTUITYPE_AUTHOR
,
1269 &doc
->basedoc
.IOleInPlaceActiveObject_iface
, &doc
->basedoc
.IOleCommandTarget_iface
,
1270 doc
->frame
, doc
->ip_window
);
1273 call_set_active_object(doc
->ip_window
, &doc
->basedoc
.IOleInPlaceActiveObject_iface
);
1275 SetRectEmpty(&rcBorderWidths
);
1277 IOleInPlaceFrame_SetBorderSpace(doc
->frame
, &rcBorderWidths
);