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
30 #include "wine/debug.h"
32 #include "mshtml_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
37 #define NSCMD_ALIGN "cmd_align"
38 #define NSCMD_BEGINLINE "cmd_beginLine"
39 #define NSCMD_BOLD "cmd_bold"
40 #define NSCMD_CHARNEXT "cmd_charNext"
41 #define NSCMD_CHARPREVIOUS "cmd_charPrevious"
42 #define NSCMD_COPY "cmd_copy"
43 #define NSCMD_CUT "cmd_cut"
44 #define NSCMD_DELETECHARFORWARD "cmd_deleteCharForward"
45 #define NSCMD_DELETEWORDFORWARD "cmd_deleteWordForward"
46 #define NSCMD_ENDLINE "cmd_endLine"
47 #define NSCMD_FONTCOLOR "cmd_fontColor"
48 #define NSCMD_FONTFACE "cmd_fontFace"
49 #define NSCMD_INDENT "cmd_indent"
50 #define NSCMD_INSERTHR "cmd_insertHR"
51 #define NSCMD_INSERTLINKNOUI "cmd_insertLinkNoUI"
52 #define NSCMD_ITALIC "cmd_italic"
53 #define NSCMD_LINENEXT "cmd_lineNext"
54 #define NSCMD_LINEPREVIOUS "cmd_linePrevious"
55 #define NSCMD_MOVEBOTTOM "cmd_moveBottom"
56 #define NSCMD_MOVEPAGEDOWN "cmd_movePageDown"
57 #define NSCMD_MOVEPAGEUP "cmd_movePageUp"
58 #define NSCMD_MOVETOP "cmd_moveTop"
59 #define NSCMD_OL "cmd_ol"
60 #define NSCMD_OUTDENT "cmd_outdent"
61 #define NSCMD_PASTE "cmd_paste"
62 #define NSCMD_SELECTALL "cmd_selectAll"
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 static const WCHAR fontW
[] = {'f','o','n','t',0};
96 static const WCHAR sizeW
[] = {'s','i','z','e',0};
98 void set_dirty(HTMLDocument
*This
, VARIANT_BOOL dirty
)
102 if(This
->doc_obj
->usermode
!= EDITMODE
|| !This
->doc_obj
->nscontainer
|| !This
->doc_obj
->nscontainer
->editor
)
106 nsres
= nsIEditor_IncrementModificationCount(This
->doc_obj
->nscontainer
->editor
, 1);
108 ERR("IncrementModificationCount failed: %08x\n", nsres
);
110 nsres
= nsIEditor_ResetModificationCount(This
->doc_obj
->nscontainer
->editor
);
112 ERR("ResetModificationCount failed: %08x\n", nsres
);
116 static void do_ns_editor_command(NSContainer
*This
, const char *cmd
)
120 if(!This
->editor_controller
)
123 nsres
= nsIController_DoCommand(This
->editor_controller
, cmd
);
125 ERR("DoCommand(%s) failed: %08x\n", debugstr_a(cmd
), nsres
);
128 static nsresult
get_ns_command_state(NSContainer
*This
, const char *cmd
, nsICommandParams
*nsparam
)
130 nsICommandManager
*cmdmgr
;
133 nsres
= get_nsinterface((nsISupports
*)This
->webbrowser
, &IID_nsICommandManager
, (void**)&cmdmgr
);
134 if(NS_FAILED(nsres
)) {
135 ERR("Could not get nsICommandManager: %08x\n", nsres
);
139 nsres
= nsICommandManager_GetCommandState(cmdmgr
, cmd
, This
->doc
->basedoc
.window
->nswindow
, nsparam
);
141 ERR("GetCommandState(%s) failed: %08x\n", debugstr_a(cmd
), nsres
);
143 nsICommandManager_Release(cmdmgr
);
147 static DWORD
query_ns_edit_status(HTMLDocument
*This
, const char *nscmd
)
149 nsICommandParams
*nsparam
;
152 if(This
->doc_obj
->usermode
!= EDITMODE
|| This
->window
->readystate
< READYSTATE_INTERACTIVE
)
153 return OLECMDF_SUPPORTED
;
155 if(This
->doc_obj
->nscontainer
&& nscmd
) {
156 nsparam
= create_nscommand_params();
157 get_ns_command_state(This
->doc_obj
->nscontainer
, nscmd
, nsparam
);
159 nsICommandParams_GetBooleanValue(nsparam
, NSSTATE_ALL
, &b
);
161 nsICommandParams_Release(nsparam
);
164 return OLECMDF_SUPPORTED
| OLECMDF_ENABLED
| (b
? OLECMDF_LATCHED
: 0);
167 static void set_ns_align(HTMLDocument
*This
, const char *align_str
)
169 nsICommandParams
*nsparam
;
171 if(!This
->doc_obj
->nscontainer
)
174 nsparam
= create_nscommand_params();
175 nsICommandParams_SetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, align_str
);
177 do_ns_command(This
, NSCMD_ALIGN
, nsparam
);
179 nsICommandParams_Release(nsparam
);
182 static DWORD
query_align_status(HTMLDocument
*This
, const WCHAR
*align
)
184 DWORD ret
= OLECMDF_SUPPORTED
| OLECMDF_ENABLED
;
185 nsAString justify_str
;
189 if(This
->doc_obj
->usermode
!= EDITMODE
|| This
->window
->readystate
< READYSTATE_INTERACTIVE
)
190 return OLECMDF_SUPPORTED
;
192 nsAString_Init(&justify_str
, align
);
193 nsres
= nsIDOMHTMLDocument_QueryCommandState(This
->doc_node
->nsdoc
, &justify_str
, &b
);
194 nsAString_Finish(&justify_str
);
195 if(NS_SUCCEEDED(nsres
) && b
)
196 ret
|= OLECMDF_LATCHED
;
202 static nsISelection
*get_ns_selection(HTMLDocument
*This
)
204 nsISelection
*nsselection
= NULL
;
207 nsres
= nsIDOMWindow_GetSelection(This
->window
->nswindow
, &nsselection
);
209 ERR("GetSelection failed %08x\n", nsres
);
215 static void remove_child_attr(nsIDOMElement
*elem
, LPCWSTR tag
, nsAString
*attr_str
)
217 cpp_bool has_children
;
218 PRUint32 child_cnt
, i
;
219 nsIDOMNode
*child_node
;
220 nsIDOMNodeList
*node_list
;
223 nsIDOMElement_HasChildNodes(elem
, &has_children
);
227 nsIDOMElement_GetChildNodes(elem
, &node_list
);
228 nsIDOMNodeList_GetLength(node_list
, &child_cnt
);
230 for(i
=0; i
<child_cnt
; i
++) {
231 nsIDOMNodeList_Item(node_list
, i
, &child_node
);
233 nsIDOMNode_GetNodeType(child_node
, &node_type
);
234 if(node_type
== ELEMENT_NODE
) {
235 nsIDOMElement
*child_elem
;
237 const PRUnichar
*ctag
;
239 nsIDOMNode_QueryInterface(child_node
, &IID_nsIDOMElement
, (void**)&child_elem
);
241 nsAString_Init(&tag_str
, NULL
);
242 nsIDOMElement_GetTagName(child_elem
, &tag_str
);
243 nsAString_GetData(&tag_str
, &ctag
);
245 if(!strcmpiW(ctag
, tag
))
246 /* FIXME: remove node if there are no more attributes */
247 nsIDOMElement_RemoveAttribute(child_elem
, attr_str
);
249 nsAString_Finish(&tag_str
);
251 remove_child_attr(child_elem
, tag
, attr_str
);
253 nsIDOMNode_Release(child_elem
);
256 nsIDOMNode_Release(child_node
);
259 nsIDOMNodeList_Release(node_list
);
262 static void get_font_size(HTMLDocument
*This
, WCHAR
*ret
)
264 nsISelection
*nsselection
= get_ns_selection(This
);
265 nsIDOMElement
*elem
= NULL
;
266 nsIDOMNode
*node
= NULL
, *tmp_node
;
277 nsISelection_GetFocusNode(nsselection
, &node
);
278 nsISelection_Release(nsselection
);
281 nsres
= nsIDOMNode_GetNodeType(node
, &node_type
);
282 if(NS_FAILED(nsres
) || node_type
== DOCUMENT_NODE
)
285 if(node_type
== ELEMENT_NODE
) {
286 nsIDOMNode_QueryInterface(node
, &IID_nsIDOMElement
, (void**)&elem
);
288 nsAString_Init(&tag_str
, NULL
);
289 nsIDOMElement_GetTagName(elem
, &tag_str
);
290 nsAString_GetData(&tag_str
, &tag
);
292 if(!strcmpiW(tag
, fontW
)) {
293 nsAString size_str
, val_str
;
296 TRACE("found font tag %p\n", elem
);
298 nsAString_InitDepend(&size_str
, sizeW
);
299 nsAString_Init(&val_str
, NULL
);
301 nsIDOMElement_GetAttribute(elem
, &size_str
, &val_str
);
302 nsAString_GetData(&val_str
, &val
);
305 TRACE("found size %s\n", debugstr_w(val
));
309 nsAString_Finish(&size_str
);
310 nsAString_Finish(&val_str
);
313 nsAString_Finish(&tag_str
);
315 nsIDOMElement_Release(elem
);
322 nsIDOMNode_GetParentNode(node
, &node
);
323 nsIDOMNode_Release(tmp_node
);
327 nsIDOMNode_Release(node
);
330 static void set_font_size(HTMLDocument
*This
, LPCWSTR size
)
332 nsISelection
*nsselection
;
334 nsIDOMHTMLElement
*elem
;
336 PRInt32 range_cnt
= 0;
340 if(!This
->doc_node
->nsdoc
) {
341 WARN("NULL nsdoc\n");
345 nsselection
= get_ns_selection(This
);
349 nsISelection_GetRangeCount(nsselection
, &range_cnt
);
351 FIXME("range_cnt %d not supprted\n", range_cnt
);
353 nsISelection_Release(nsselection
);
358 create_nselem(This
->doc_node
, fontW
, &elem
);
360 nsAString_InitDepend(&size_str
, sizeW
);
361 nsAString_InitDepend(&val_str
, size
);
363 nsIDOMElement_SetAttribute(elem
, &size_str
, &val_str
);
364 nsAString_Finish(&val_str
);
366 nsISelection_GetRangeAt(nsselection
, 0, &range
);
367 nsISelection_GetIsCollapsed(nsselection
, &collapsed
);
368 nsISelection_RemoveAllRanges(nsselection
);
370 nsIDOMRange_SurroundContents(range
, (nsIDOMNode
*)elem
);
373 nsISelection_Collapse(nsselection
, (nsIDOMNode
*)elem
, 0);
375 /* Remove all size attributes from the range */
376 remove_child_attr((nsIDOMElement
*)elem
, fontW
, &size_str
);
377 nsISelection_SelectAllChildren(nsselection
, (nsIDOMNode
*)elem
);
380 nsISelection_Release(nsselection
);
381 nsIDOMRange_Release(range
);
382 nsIDOMElement_Release(elem
);
384 nsAString_Finish(&size_str
);
386 set_dirty(This
, VARIANT_TRUE
);
389 static void handle_arrow_key(HTMLDocument
*This
, nsIDOMKeyEvent
*event
, const char * const cmds
[4])
394 nsIDOMKeyEvent_GetCtrlKey(event
, &b
);
398 nsIDOMKeyEvent_GetShiftKey(event
, &b
);
403 do_ns_editor_command(This
->doc_obj
->nscontainer
, cmds
[i
]);
405 nsIDOMKeyEvent_PreventDefault(event
);
408 void handle_edit_event(HTMLDocument
*This
, nsIDOMEvent
*event
)
410 nsIDOMKeyEvent
*key_event
;
413 nsIDOMEvent_QueryInterface(event
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
415 nsIDOMKeyEvent_GetKeyCode(key_event
, &code
);
419 static const char * const cmds
[] = {
422 NSCMD_SELECTCHARPREVIOUS
,
423 NSCMD_SELECTWORDPREVIOUS
427 handle_arrow_key(This
, key_event
, cmds
);
431 static const char * const cmds
[] = {
434 NSCMD_SELECTCHARNEXT
,
439 handle_arrow_key(This
, key_event
, cmds
);
443 static const char * const cmds
[] = {
446 NSCMD_SELECTLINEPREVIOUS
,
451 handle_arrow_key(This
, key_event
, cmds
);
455 static const char * const cmds
[] = {
458 NSCMD_SELECTLINENEXT
,
463 handle_arrow_key(This
, key_event
, cmds
);
466 case DOM_VK_DELETE
: {
467 static const char * const cmds
[] = {
468 NSCMD_DELETECHARFORWARD
,
469 NSCMD_DELETEWORDFORWARD
,
474 handle_arrow_key(This
, key_event
, cmds
);
478 static const char * const cmds
[] = {
481 NSCMD_SELECTBEGINLINE
,
486 handle_arrow_key(This
, key_event
, cmds
);
490 static const char * const cmds
[] = {
498 handle_arrow_key(This
, key_event
, cmds
);
503 nsIDOMKeyEvent_Release(key_event
);
506 void handle_edit_load(HTMLDocument
*This
)
508 get_editor_controller(This
->doc_obj
->nscontainer
);
511 static void set_ns_fontname(HTMLDocument
*This
, const char *fontname
)
513 nsICommandParams
*nsparam
= create_nscommand_params();
515 nsICommandParams_SetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, fontname
);
516 do_ns_command(This
, NSCMD_FONTFACE
, nsparam
);
517 nsICommandParams_Release(nsparam
);
520 static HRESULT
exec_delete(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
522 TRACE("(%p)->(%p %p)\n", This
, in
, out
);
524 if(This
->doc_obj
->nscontainer
)
525 do_ns_editor_command(This
->doc_obj
->nscontainer
, NSCMD_DELETECHARFORWARD
);
527 update_doc(This
, UPDATE_UI
);
531 static HRESULT
exec_fontname(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
533 TRACE("(%p)->(%p %p)\n", This
, in
, out
);
535 if(!This
->doc_obj
->nscontainer
) {
536 update_doc(This
, UPDATE_UI
);
543 if(V_VT(in
) != VT_BSTR
) {
544 FIXME("Unsupported vt=%d\n", V_VT(out
));
548 TRACE("%s\n", debugstr_w(V_BSTR(in
)));
550 stra
= heap_strdupWtoA(V_BSTR(in
));
551 set_ns_fontname(This
, stra
);
554 update_doc(This
, UPDATE_UI
);
558 nsICommandParams
*nsparam
;
567 nsparam
= create_nscommand_params();
569 nsres
= get_ns_command_state(This
->doc_obj
->nscontainer
, NSCMD_FONTFACE
, nsparam
);
573 nsICommandParams_GetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, &stra
);
574 nsICommandParams_Release(nsparam
);
576 len
= MultiByteToWideChar(CP_ACP
, 0, stra
, -1, NULL
, 0);
577 strw
= heap_alloc(len
*sizeof(WCHAR
));
578 MultiByteToWideChar(CP_ACP
, 0, stra
, -1, strw
, len
);
581 V_BSTR(out
) = SysAllocString(strw
);
588 static HRESULT
exec_forecolor(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
590 TRACE("(%p)->(%p %p)\n", This
, in
, out
);
593 if(V_VT(in
) == VT_I4
) {
594 nsICommandParams
*nsparam
= create_nscommand_params();
597 sprintf(color_str
, "#%02x%02x%02x",
598 V_I4(in
)&0xff, (V_I4(in
)>>8)&0xff, (V_I4(in
)>>16)&0xff);
600 nsICommandParams_SetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, color_str
);
601 do_ns_command(This
, NSCMD_FONTCOLOR
, nsparam
);
603 nsICommandParams_Release(nsparam
);
605 FIXME("unsupported in vt=%d\n", V_VT(in
));
608 update_doc(This
, UPDATE_UI
);
612 FIXME("unsupported out\n");
619 static HRESULT
exec_fontsize(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
621 TRACE("(%p)->(%p %p)\n", This
, in
, out
);
626 get_font_size(This
, val
);
628 V_I4(out
) = strtolW(val
, NULL
, 10);
635 static const WCHAR format
[] = {'%','d',0};
636 wsprintfW(size
, format
, V_I4(in
));
637 set_font_size(This
, size
);
641 set_font_size(This
, V_BSTR(in
));
644 FIXME("unsupported vt %d\n", V_VT(in
));
647 update_doc(This
, UPDATE_UI
);
653 static HRESULT
exec_font(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
656 FIXME("(%p)->(%p %p)\n", This
, in
, out
);
660 static HRESULT
exec_selectall(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
662 TRACE("(%p)\n", This
);
665 FIXME("unsupported args\n");
667 if(This
->doc_obj
->nscontainer
)
668 do_ns_command(This
, NSCMD_SELECTALL
, NULL
);
670 update_doc(This
, UPDATE_UI
);
674 static HRESULT
exec_bold(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
676 TRACE("(%p)\n", This
);
679 FIXME("unsupported args\n");
681 if(This
->doc_obj
->nscontainer
)
682 do_ns_command(This
, NSCMD_BOLD
, NULL
);
684 update_doc(This
, UPDATE_UI
);
688 static HRESULT
exec_italic(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
690 TRACE("(%p)\n", This
);
693 FIXME("unsupported args\n");
695 if(This
->doc_obj
->nscontainer
)
696 do_ns_command(This
, NSCMD_ITALIC
, NULL
);
698 update_doc(This
, UPDATE_UI
);
702 static HRESULT
query_justify(HTMLDocument
*This
, OLECMD
*cmd
)
704 static const PRUnichar justifycenterW
[] = {'j','u','s','t','i','f','y','c','e','n','t','e','r',0};
705 static const PRUnichar justifyrightW
[] = {'j','u','s','t','i','f','y','r','i','g','h','t',0};
708 case IDM_JUSTIFYCENTER
:
709 TRACE("(%p) IDM_JUSTIFYCENTER\n", This
);
710 cmd
->cmdf
= query_align_status(This
, justifycenterW
);
712 case IDM_JUSTIFYLEFT
:
713 TRACE("(%p) IDM_JUSTIFYLEFT\n", This
);
714 /* FIXME: We should set OLECMDF_LATCHED only if it's set explicitly. */
715 if(This
->doc_obj
->usermode
!= EDITMODE
|| This
->window
->readystate
< READYSTATE_INTERACTIVE
)
716 cmd
->cmdf
= OLECMDF_SUPPORTED
;
718 cmd
->cmdf
= OLECMDF_SUPPORTED
| OLECMDF_ENABLED
;
720 case IDM_JUSTIFYRIGHT
:
721 TRACE("(%p) IDM_JUSTIFYRIGHT\n", This
);
722 cmd
->cmdf
= query_align_status(This
, justifyrightW
);
729 static HRESULT
exec_justifycenter(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
731 TRACE("(%p)\n", This
);
734 FIXME("unsupported args\n");
736 set_ns_align(This
, NSALIGN_CENTER
);
737 update_doc(This
, UPDATE_UI
);
741 static HRESULT
exec_justifyleft(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
743 TRACE("(%p)\n", This
);
746 FIXME("unsupported args\n");
748 set_ns_align(This
, NSALIGN_LEFT
);
749 update_doc(This
, UPDATE_UI
);
753 static HRESULT
exec_justifyright(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
755 TRACE("(%p)\n", This
);
758 FIXME("unsupported args\n");
760 set_ns_align(This
, NSALIGN_RIGHT
);
761 update_doc(This
, UPDATE_UI
);
765 static HRESULT
exec_underline(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
767 TRACE("(%p)\n", This
);
770 FIXME("unsupported args\n");
772 do_ns_command(This
, NSCMD_UNDERLINE
, NULL
);
773 update_doc(This
, UPDATE_UI
);
777 static HRESULT
exec_horizontalline(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
779 TRACE("(%p)\n", This
);
782 FIXME("unsupported args\n");
784 do_ns_command(This
, NSCMD_INSERTHR
, NULL
);
785 update_doc(This
, UPDATE_UI
);
789 static HRESULT
exec_orderlist(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
791 TRACE("(%p)\n", This
);
794 FIXME("unsupported args\n");
796 do_ns_command(This
, NSCMD_OL
, NULL
);
797 update_doc(This
, UPDATE_UI
);
801 static HRESULT
exec_unorderlist(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
803 TRACE("(%p)\n", This
);
806 FIXME("unsupported args\n");
808 do_ns_command(This
, NSCMD_UL
, NULL
);
809 update_doc(This
, UPDATE_UI
);
813 static HRESULT
exec_indent(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
815 TRACE("(%p)\n", This
);
818 FIXME("unsupported args\n");
820 do_ns_command(This
, NSCMD_INDENT
, NULL
);
821 update_doc(This
, UPDATE_UI
);
825 static HRESULT
exec_outdent(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
827 TRACE("(%p)\n", This
);
830 FIXME("unsupported args\n");
832 do_ns_command(This
, NSCMD_OUTDENT
, NULL
);
833 update_doc(This
, UPDATE_UI
);
837 static HRESULT
exec_composesettings(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
841 if(out
|| !in
|| V_VT(in
) != VT_BSTR
) {
842 WARN("invalid arg\n");
846 TRACE("(%p)->(%x %s)\n", This
, cmdexecopt
, debugstr_w(V_BSTR(in
)));
848 update_doc(This
, UPDATE_UI
);
852 exec_bold(This
, cmdexecopt
, NULL
, NULL
);
853 ptr
= strchrW(ptr
, ',');
858 exec_italic(This
, cmdexecopt
, NULL
, NULL
);
859 ptr
= strchrW(ptr
, ',');
864 exec_underline(This
, cmdexecopt
, NULL
, NULL
);
865 ptr
= strchrW(ptr
, ',');
869 if(isdigitW(*++ptr
)) {
875 exec_fontsize(This
, cmdexecopt
, &v
, NULL
);
877 ptr
= strchrW(ptr
, ',');
882 FIXME("set font color\n");
883 ptr
= strchrW(ptr
, ',');
888 FIXME("set background color\n");
889 ptr
= strchrW(ptr
, ',');
898 V_BSTR(&v
) = SysAllocString(ptr
);
900 exec_fontname(This
, cmdexecopt
, &v
, NULL
);
902 SysFreeString(V_BSTR(&v
));
908 HRESULT
editor_exec_copy(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
910 update_doc(This
, UPDATE_UI
);
912 if(!This
->doc_obj
->nscontainer
)
915 do_ns_editor_command(This
->doc_obj
->nscontainer
, NSCMD_COPY
);
919 HRESULT
editor_exec_cut(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
921 update_doc(This
, UPDATE_UI
);
923 if(!This
->doc_obj
->nscontainer
)
926 do_ns_editor_command(This
->doc_obj
->nscontainer
, NSCMD_CUT
);
930 HRESULT
editor_exec_paste(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
932 update_doc(This
, UPDATE_UI
);
934 if(!This
->doc_obj
->nscontainer
)
937 do_ns_editor_command(This
->doc_obj
->nscontainer
, NSCMD_PASTE
);
941 static HRESULT
exec_setdirty(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
943 TRACE("(%p)->(%08x %p %p)\n", This
, cmdexecopt
, in
, out
);
948 if(V_VT(in
) == VT_BOOL
)
949 set_dirty(This
, V_BOOL(in
));
951 FIXME("unsupported vt=%d\n", V_VT(in
));
956 static HRESULT
query_edit_status(HTMLDocument
*This
, OLECMD
*cmd
)
960 TRACE("CGID_MSHTML: IDM_DELETE\n");
961 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
964 TRACE("CGID_MSHTML: IDM_FONTNAME\n");
965 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
968 TRACE("CGID_MSHTML: IDM_FONTSIZE\n");
969 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
972 TRACE("CGID_MSHTML: IDM_BOLD\n");
973 cmd
->cmdf
= query_ns_edit_status(This
, NSCMD_BOLD
);
976 TRACE("CGID_MSHTML: IDM_FORECOLOR\n");
977 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
980 TRACE("CGID_MSHTML: IDM_ITALIC\n");
981 cmd
->cmdf
= query_ns_edit_status(This
, NSCMD_ITALIC
);
984 TRACE("CGID_MSHTML: IDM_UNDERLINE\n");
985 cmd
->cmdf
= query_ns_edit_status(This
, NSCMD_UNDERLINE
);
987 case IDM_HORIZONTALLINE
:
988 TRACE("CGID_MSHTML: IDM_HORIZONTALLINE\n");
989 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
992 TRACE("CGID_MSHTML: IDM_ORDERLIST\n");
993 cmd
->cmdf
= query_ns_edit_status(This
, NSCMD_OL
);
995 case IDM_UNORDERLIST
:
996 TRACE("CGID_MSHTML: IDM_HORIZONTALLINE\n");
997 cmd
->cmdf
= query_ns_edit_status(This
, NSCMD_UL
);
1000 TRACE("CGID_MSHTML: IDM_INDENT\n");
1001 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1004 TRACE("CGID_MSHTML: IDM_OUTDENT\n");
1005 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1008 TRACE("CGID_MSHTML: IDM_HYPERLINK\n");
1009 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1016 static INT_PTR CALLBACK
hyperlink_dlgproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1018 static const WCHAR wszOther
[] = {'(','o','t','h','e','r',')',0};
1024 static const WCHAR wszFile
[] = {'f','i','l','e',':',0};
1025 static const WCHAR wszFtp
[] = {'f','t','p',':',0};
1026 static const WCHAR wszHttp
[] = {'h','t','t','p',':',0};
1027 static const WCHAR wszHttps
[] = {'h','t','t','p','s',':',0};
1028 static const WCHAR wszMailto
[] = {'m','a','i','l','t','o',':',0};
1029 static const WCHAR wszNews
[] = {'n','e','w','s',':',0};
1031 HWND hwndCB
= GetDlgItem(hwnd
, IDC_TYPE
);
1032 HWND hwndURL
= GetDlgItem(hwnd
, IDC_URL
);
1035 SetWindowLongPtrW(hwnd
, DWLP_USER
, lparam
);
1037 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszOther
);
1038 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszFile
);
1039 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszFtp
);
1040 def_idx
= SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszHttp
);
1041 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszHttps
);
1042 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszMailto
);
1043 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszNews
);
1044 SendMessageW(hwndCB
, CB_SETCURSEL
, def_idx
, 0);
1046 /* force the updating of the URL edit box */
1047 SendMessageW(hwnd
, WM_COMMAND
, MAKEWPARAM(IDC_TYPE
, CBN_SELCHANGE
), (LPARAM
)hwndCB
);
1050 len
= SendMessageW(hwndURL
, WM_GETTEXTLENGTH
, 0, 0);
1051 SendMessageW(hwndURL
, EM_SETSEL
, 0, len
);
1058 case MAKEWPARAM(IDCANCEL
, BN_CLICKED
):
1059 EndDialog(hwnd
, wparam
);
1061 case MAKEWPARAM(IDOK
, BN_CLICKED
):
1063 BSTR
*url
= (BSTR
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1064 HWND hwndURL
= GetDlgItem(hwnd
, IDC_URL
);
1065 INT len
= GetWindowTextLengthW(hwndURL
);
1066 *url
= SysAllocStringLen(NULL
, len
+ 1);
1067 GetWindowTextW(hwndURL
, *url
, len
+ 1);
1068 EndDialog(hwnd
, wparam
);
1071 case MAKEWPARAM(IDC_TYPE
, CBN_SELCHANGE
):
1073 HWND hwndURL
= GetDlgItem(hwnd
, IDC_URL
);
1079 static const WCHAR wszSlashSlash
[] = {'/','/'};
1081 /* get string of currently selected hyperlink type */
1082 item
= SendMessageW((HWND
)lparam
, CB_GETCURSEL
, 0, 0);
1083 len
= SendMessageW((HWND
)lparam
, CB_GETLBTEXTLEN
, item
, 0);
1084 type
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
1085 SendMessageW((HWND
)lparam
, CB_GETLBTEXT
, item
, (LPARAM
)type
);
1087 if (!strcmpW(type
, wszOther
))
1090 /* get current URL */
1091 len
= GetWindowTextLengthW(hwndURL
);
1092 url
= HeapAlloc(GetProcessHeap(), 0, (len
+ strlenW(type
) + 3) * sizeof(WCHAR
));
1093 GetWindowTextW(hwndURL
, url
, len
+ 1);
1095 /* strip off old protocol */
1096 p
= strchrW(url
, ':');
1097 if (p
&& p
[1] == '/' && p
[2] == '/')
1100 memmove(url
+ (*type
!= '\0' ? strlenW(type
) + 2 : 0), p
, (len
+ 1 - (p
- url
)) * sizeof(WCHAR
));
1102 /* add new protocol */
1105 memcpy(url
, type
, strlenW(type
) * sizeof(WCHAR
));
1106 memcpy(url
+ strlenW(type
), wszSlashSlash
, sizeof(wszSlashSlash
));
1109 SetWindowTextW(hwndURL
, url
);
1111 HeapFree(GetProcessHeap(), 0, url
);
1112 HeapFree(GetProcessHeap(), 0, type
);
1118 EndDialog(hwnd
, IDCANCEL
);
1125 static HRESULT
exec_hyperlink(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
1127 nsAString href_str
, ns_url
;
1128 nsIHTMLEditor
*html_editor
;
1129 nsIDOMHTMLElement
*anchor_elem
;
1130 cpp_bool insert_link_at_caret
;
1131 nsISelection
*nsselection
;
1134 HRESULT hres
= E_FAIL
;
1136 static const WCHAR aW
[] = {'a',0};
1137 static const WCHAR hrefW
[] = {'h','r','e','f',0};
1139 TRACE("%p, 0x%x, %p, %p\n", This
, cmdexecopt
, in
, out
);
1141 if (cmdexecopt
== OLECMDEXECOPT_DONTPROMPTUSER
)
1143 if (!in
|| V_VT(in
) != VT_BSTR
)
1145 WARN("invalid arg\n");
1146 return E_INVALIDARG
;
1152 ret
= DialogBoxParamW(hInst
, MAKEINTRESOURCEW(IDD_HYPERLINK
), NULL
/* FIXME */, hyperlink_dlgproc
, (LPARAM
)&url
);
1154 return OLECMDERR_E_CANCELED
;
1157 if(!This
->doc_node
->nsdoc
) {
1158 WARN("NULL nsdoc\n");
1159 return E_UNEXPECTED
;
1162 nsselection
= get_ns_selection(This
);
1166 /* create an element for the link */
1167 create_nselem(This
->doc_node
, aW
, &anchor_elem
);
1169 nsAString_InitDepend(&href_str
, hrefW
);
1170 nsAString_InitDepend(&ns_url
, url
);
1171 nsIDOMElement_SetAttribute(anchor_elem
, &href_str
, &ns_url
);
1172 nsAString_Finish(&href_str
);
1174 nsISelection_GetIsCollapsed(nsselection
, &insert_link_at_caret
);
1176 /* create an element with text of URL */
1177 if (insert_link_at_caret
) {
1178 nsIDOMNode
*text_node
, *unused_node
;
1180 nsIDOMDocument_CreateTextNode(This
->doc_node
->nsdoc
, &ns_url
, (nsIDOMText
**)&text_node
);
1182 /* wrap the <a> tags around the text element */
1183 nsIDOMElement_AppendChild(anchor_elem
, text_node
, &unused_node
);
1184 nsIDOMNode_Release(text_node
);
1185 nsIDOMNode_Release(unused_node
);
1188 nsAString_Finish(&ns_url
);
1190 nsIEditor_QueryInterface(This
->doc_obj
->nscontainer
->editor
, &IID_nsIHTMLEditor
, (void **)&html_editor
);
1194 if (insert_link_at_caret
) {
1195 /* add them to the document at the caret position */
1196 nsres
= nsIHTMLEditor_InsertElementAtSelection(html_editor
, (nsIDOMElement
*)anchor_elem
, FALSE
);
1197 nsISelection_SelectAllChildren(nsselection
, (nsIDOMNode
*)anchor_elem
);
1198 }else /* add them around the selection using the magic provided to us by nsIHTMLEditor */
1199 nsres
= nsIHTMLEditor_InsertLinkAroundSelection(html_editor
, (nsIDOMElement
*)anchor_elem
);
1201 nsIHTMLEditor_Release(html_editor
);
1202 hres
= NS_SUCCEEDED(nsres
) ? S_OK
: E_FAIL
;
1205 nsISelection_Release(nsselection
);
1206 nsIDOMElement_Release(anchor_elem
);
1208 if (cmdexecopt
!= OLECMDEXECOPT_DONTPROMPTUSER
)
1211 TRACE("-- 0x%08x\n", hres
);
1215 static HRESULT
query_selall_status(HTMLDocument
*This
, OLECMD
*cmd
)
1217 TRACE("(%p)->(%p)\n", This
, cmd
);
1219 cmd
->cmdf
= OLECMDF_SUPPORTED
|OLECMDF_ENABLED
;
1223 const cmdtable_t editmode_cmds
[] = {
1224 {IDM_DELETE
, query_edit_status
, exec_delete
},
1225 {IDM_FONTNAME
, query_edit_status
, exec_fontname
},
1226 {IDM_FONTSIZE
, query_edit_status
, exec_fontsize
},
1227 {IDM_SELECTALL
, query_selall_status
, exec_selectall
},
1228 {IDM_FORECOLOR
, query_edit_status
, exec_forecolor
},
1229 {IDM_BOLD
, query_edit_status
, exec_bold
},
1230 {IDM_ITALIC
, query_edit_status
, exec_italic
},
1231 {IDM_JUSTIFYCENTER
, query_justify
, exec_justifycenter
},
1232 {IDM_JUSTIFYRIGHT
, query_justify
, exec_justifyright
},
1233 {IDM_JUSTIFYLEFT
, query_justify
, exec_justifyleft
},
1234 {IDM_FONT
, NULL
, exec_font
},
1235 {IDM_UNDERLINE
, query_edit_status
, exec_underline
},
1236 {IDM_HORIZONTALLINE
, query_edit_status
, exec_horizontalline
},
1237 {IDM_ORDERLIST
, query_edit_status
, exec_orderlist
},
1238 {IDM_UNORDERLIST
, query_edit_status
, exec_unorderlist
},
1239 {IDM_INDENT
, query_edit_status
, exec_indent
},
1240 {IDM_OUTDENT
, query_edit_status
, exec_outdent
},
1241 {IDM_COMPOSESETTINGS
, NULL
, exec_composesettings
},
1242 {IDM_HYPERLINK
, query_edit_status
, exec_hyperlink
},
1243 {IDM_SETDIRTY
, NULL
, exec_setdirty
},
1247 void init_editor(HTMLDocument
*This
)
1249 update_doc(This
, UPDATE_UI
);
1251 set_ns_fontname(This
, "Times New Roman");
1254 HRESULT
editor_is_dirty(HTMLDocument
*This
)
1258 if(!This
->doc_obj
->nscontainer
|| !This
->doc_obj
->nscontainer
->editor
)
1261 nsIEditor_GetDocumentModified(This
->doc_obj
->nscontainer
->editor
, &modified
);
1263 return modified
? S_OK
: S_FALSE
;