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
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
36 #include "mshtml_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
41 #define NSCMD_ALIGN "cmd_align"
42 #define NSCMD_BEGINLINE "cmd_beginLine"
43 #define NSCMD_BOLD "cmd_bold"
44 #define NSCMD_CHARNEXT "cmd_charNext"
45 #define NSCMD_CHARPREVIOUS "cmd_charPrevious"
46 #define NSCMD_COPY "cmd_copy"
47 #define NSCMD_CUT "cmd_cut"
48 #define NSCMD_DELETECHARFORWARD "cmd_deleteCharForward"
49 #define NSCMD_DELETEWORDFORWARD "cmd_deleteWordForward"
50 #define NSCMD_ENDLINE "cmd_endLine"
51 #define NSCMD_FONTCOLOR "cmd_fontColor"
52 #define NSCMD_FONTFACE "cmd_fontFace"
53 #define NSCMD_INDENT "cmd_indent"
54 #define NSCMD_INSERTHR "cmd_insertHR"
55 #define NSCMD_INSERTLINKNOUI "cmd_insertLinkNoUI"
56 #define NSCMD_ITALIC "cmd_italic"
57 #define NSCMD_LINENEXT "cmd_lineNext"
58 #define NSCMD_LINEPREVIOUS "cmd_linePrevious"
59 #define NSCMD_MOVEBOTTOM "cmd_moveBottom"
60 #define NSCMD_MOVEPAGEDOWN "cmd_movePageDown"
61 #define NSCMD_MOVEPAGEUP "cmd_movePageUp"
62 #define NSCMD_MOVETOP "cmd_moveTop"
63 #define NSCMD_OL "cmd_ol"
64 #define NSCMD_OUTDENT "cmd_outdent"
65 #define NSCMD_PASTE "cmd_paste"
66 #define NSCMD_SELECTALL "cmd_selectAll"
67 #define NSCMD_SELECTBEGINLINE "cmd_selectBeginLine"
68 #define NSCMD_SELECTBOTTOM "cmd_selectBottom"
69 #define NSCMD_SELECTCHARNEXT "cmd_selectCharNext"
70 #define NSCMD_SELECTCHARPREVIOUS "cmd_selectCharPrevious"
71 #define NSCMD_SELECTENDLINE "cmd_selectEndLine"
72 #define NSCMD_SELECTLINENEXT "cmd_selectLineNext"
73 #define NSCMD_SELECTLINEPREVIOUS "cmd_selectLinePrevious"
74 #define NSCMD_SELECTPAGEDOWN "cmd_selectPageDown"
75 #define NSCMD_SELECTPAGEUP "cmd_selectPageUp"
76 #define NSCMD_SELECTTOP "cmd_selectTop"
77 #define NSCMD_SELECTWORDNEXT "cmd_selectWordNext"
78 #define NSCMD_SELECTWORDPREVIOUS "cmd_selectWordPrevious"
79 #define NSCMD_UL "cmd_ul"
80 #define NSCMD_UNDERLINE "cmd_underline"
81 #define NSCMD_WORDNEXT "cmd_wordNext"
82 #define NSCMD_WORDPREVIOUS "cmd_wordPrevious"
84 #define NSSTATE_ATTRIBUTE "state_attribute"
85 #define NSSTATE_ALL "state_all"
87 #define NSALIGN_CENTER "center"
88 #define NSALIGN_LEFT "left"
89 #define NSALIGN_RIGHT "right"
91 #define DOM_VK_LEFT VK_LEFT
92 #define DOM_VK_UP VK_UP
93 #define DOM_VK_RIGHT VK_RIGHT
94 #define DOM_VK_DOWN VK_DOWN
95 #define DOM_VK_DELETE VK_DELETE
96 #define DOM_VK_HOME VK_HOME
97 #define DOM_VK_END VK_END
99 static const WCHAR wszFont
[] = {'f','o','n','t',0};
100 static const WCHAR wszSize
[] = {'s','i','z','e',0};
102 static void do_ns_command(NSContainer
*This
, const char *cmd
, nsICommandParams
*nsparam
)
104 nsICommandManager
*cmdmgr
;
105 nsIInterfaceRequestor
*iface_req
;
108 TRACE("(%p)\n", This
);
110 nsres
= nsIWebBrowser_QueryInterface(This
->webbrowser
,
111 &IID_nsIInterfaceRequestor
, (void**)&iface_req
);
112 if(NS_FAILED(nsres
)) {
113 ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres
);
117 nsres
= nsIInterfaceRequestor_GetInterface(iface_req
, &IID_nsICommandManager
,
119 nsIInterfaceRequestor_Release(iface_req
);
120 if(NS_FAILED(nsres
)) {
121 ERR("Could not get nsICommandManager: %08x\n", nsres
);
125 nsres
= nsICommandManager_DoCommand(cmdmgr
, cmd
, nsparam
, NULL
);
127 ERR("DoCommand(%s) failed: %08x\n", debugstr_a(cmd
), nsres
);
129 nsICommandManager_Release(cmdmgr
);
132 static void do_ns_editor_command(NSContainer
*This
, const char *cmd
)
136 if(!This
->editor_controller
)
139 nsres
= nsIController_DoCommand(This
->editor_controller
, cmd
);
141 ERR("DoCommand(%s) failed: %08x\n", debugstr_a(cmd
), nsres
);
144 static nsresult
get_ns_command_state(NSContainer
*This
, const char *cmd
, nsICommandParams
*nsparam
)
146 nsICommandManager
*cmdmgr
;
147 nsIInterfaceRequestor
*iface_req
;
150 nsres
= nsIWebBrowser_QueryInterface(This
->webbrowser
,
151 &IID_nsIInterfaceRequestor
, (void**)&iface_req
);
152 if(NS_FAILED(nsres
)) {
153 ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres
);
157 nsres
= nsIInterfaceRequestor_GetInterface(iface_req
, &IID_nsICommandManager
,
159 nsIInterfaceRequestor_Release(iface_req
);
160 if(NS_FAILED(nsres
)) {
161 ERR("Could not get nsICommandManager: %08x\n", nsres
);
165 nsres
= nsICommandManager_GetCommandState(cmdmgr
, cmd
, NULL
, nsparam
);
167 ERR("GetCommandState(%s) failed: %08x\n", debugstr_a(cmd
), nsres
);
169 nsICommandManager_Release(cmdmgr
);
173 static DWORD
query_ns_edit_status(HTMLDocument
*This
, const char *nscmd
)
175 nsICommandParams
*nsparam
;
178 if(This
->usermode
!= EDITMODE
|| This
->readystate
< READYSTATE_INTERACTIVE
)
179 return OLECMDF_SUPPORTED
;
181 if(This
->nscontainer
&& nscmd
) {
182 nsparam
= create_nscommand_params();
183 get_ns_command_state(This
->nscontainer
, nscmd
, nsparam
);
185 nsICommandParams_GetBooleanValue(nsparam
, NSSTATE_ALL
, &b
);
187 nsICommandParams_Release(nsparam
);
190 return OLECMDF_SUPPORTED
| OLECMDF_ENABLED
| (b
? OLECMDF_LATCHED
: 0);
193 static void set_ns_align(HTMLDocument
*This
, const char *align_str
)
195 nsICommandParams
*nsparam
;
197 if(!This
->nscontainer
)
200 nsparam
= create_nscommand_params();
201 nsICommandParams_SetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, align_str
);
203 do_ns_command(This
->nscontainer
, NSCMD_ALIGN
, nsparam
);
205 nsICommandParams_Release(nsparam
);
208 static DWORD
query_align_status(HTMLDocument
*This
, const char *align_str
)
210 nsICommandParams
*nsparam
;
213 if(This
->usermode
!= EDITMODE
|| This
->readystate
< READYSTATE_INTERACTIVE
)
214 return OLECMDF_SUPPORTED
;
216 if(This
->nscontainer
) {
217 nsparam
= create_nscommand_params();
218 get_ns_command_state(This
->nscontainer
, NSCMD_ALIGN
, nsparam
);
220 nsICommandParams_GetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, &align
);
222 nsICommandParams_Release(nsparam
);
225 return OLECMDF_SUPPORTED
| OLECMDF_ENABLED
226 | (align
&& !strcmp(align_str
, align
) ? OLECMDF_LATCHED
: 0);
230 static nsISelection
*get_ns_selection(HTMLDocument
*This
)
232 nsIDOMWindow
*dom_window
;
233 nsISelection
*nsselection
= NULL
;
236 if(!This
->nscontainer
)
239 nsres
= nsIWebBrowser_GetContentDOMWindow(This
->nscontainer
->webbrowser
, &dom_window
);
243 nsIDOMWindow_GetSelection(dom_window
, &nsselection
);
244 nsIDOMWindow_Release(dom_window
);
250 static void remove_child_attr(nsIDOMElement
*elem
, LPCWSTR tag
, nsAString
*attr_str
)
253 PRUint32 child_cnt
, i
;
254 nsIDOMNode
*child_node
;
255 nsIDOMNodeList
*node_list
;
258 nsIDOMElement_HasChildNodes(elem
, &has_children
);
262 nsIDOMElement_GetChildNodes(elem
, &node_list
);
263 nsIDOMNodeList_GetLength(node_list
, &child_cnt
);
265 for(i
=0; i
<child_cnt
; i
++) {
266 nsIDOMNodeList_Item(node_list
, i
, &child_node
);
268 nsIDOMNode_GetNodeType(child_node
, &node_type
);
269 if(node_type
== ELEMENT_NODE
) {
270 nsIDOMElement
*child_elem
;
272 const PRUnichar
*ctag
;
274 nsIDOMNode_QueryInterface(child_node
, &IID_nsIDOMElement
, (void**)&child_elem
);
276 nsAString_Init(&tag_str
, NULL
);
277 nsIDOMElement_GetTagName(child_elem
, &tag_str
);
278 nsAString_GetData(&tag_str
, &ctag
, NULL
);
280 if(!strcmpiW(ctag
, tag
))
281 /* FIXME: remove node if there are no more attributes */
282 nsIDOMElement_RemoveAttribute(child_elem
, attr_str
);
284 nsAString_Finish(&tag_str
);
286 remove_child_attr(child_elem
, tag
, attr_str
);
288 nsIDOMNode_Release(child_elem
);
291 nsIDOMNode_Release(child_node
);
294 nsIDOMNodeList_Release(node_list
);
297 static void get_font_size(HTMLDocument
*This
, WCHAR
*ret
)
299 nsISelection
*nsselection
= get_ns_selection(This
);
300 nsIDOMElement
*elem
= NULL
;
301 nsIDOMNode
*node
= NULL
, *tmp_node
;
312 nsISelection_GetFocusNode(nsselection
, &node
);
313 nsISelection_Release(nsselection
);
316 nsres
= nsIDOMNode_GetNodeType(node
, &node_type
);
317 if(NS_FAILED(nsres
) || node_type
== DOCUMENT_NODE
)
320 if(node_type
== ELEMENT_NODE
) {
321 nsIDOMNode_QueryInterface(node
, &IID_nsIDOMElement
, (void**)&elem
);
323 nsAString_Init(&tag_str
, NULL
);
324 nsIDOMElement_GetTagName(elem
, &tag_str
);
325 nsAString_GetData(&tag_str
, &tag
, NULL
);
327 if(!strcmpiW(tag
, wszFont
)) {
328 nsAString size_str
, val_str
;
331 TRACE("found font tag %p\n", elem
);
333 nsAString_Init(&size_str
, wszSize
);
334 nsAString_Init(&val_str
, NULL
);
336 nsIDOMElement_GetAttribute(elem
, &size_str
, &val_str
);
337 nsAString_GetData(&val_str
, &val
, NULL
);
340 TRACE("found size %s\n", debugstr_w(val
));
344 nsAString_Finish(&size_str
);
345 nsAString_Finish(&val_str
);
348 nsAString_Finish(&tag_str
);
350 nsIDOMElement_Release(elem
);
357 nsIDOMNode_GetParentNode(node
, &node
);
358 nsIDOMNode_Release(tmp_node
);
362 nsIDOMNode_Release(node
);
365 static void set_font_size(HTMLDocument
*This
, LPCWSTR size
)
367 nsISelection
*nsselection
;
369 nsIDOMDocument
*nsdoc
;
372 PRInt32 range_cnt
= 0;
378 nsselection
= get_ns_selection(This
);
383 nsISelection_GetRangeCount(nsselection
, &range_cnt
);
385 FIXME("range_cnt %d not supprted\n", range_cnt
);
387 nsISelection_Release(nsselection
);
392 nsres
= nsIWebNavigation_GetDocument(This
->nscontainer
->navigation
, &nsdoc
);
396 nsAString_Init(&font_str
, wszFont
);
397 nsAString_Init(&size_str
, wszSize
);
398 nsAString_Init(&val_str
, size
);
400 nsIDOMDocument_CreateElement(nsdoc
, &font_str
, &elem
);
401 nsIDOMElement_SetAttribute(elem
, &size_str
, &val_str
);
403 nsISelection_GetRangeAt(nsselection
, 0, &range
);
404 nsISelection_GetIsCollapsed(nsselection
, &collapsed
);
405 nsISelection_RemoveAllRanges(nsselection
);
407 nsIDOMRange_SurroundContents(range
, (nsIDOMNode
*)elem
);
410 nsISelection_Collapse(nsselection
, (nsIDOMNode
*)elem
, 0);
412 /* Remove all size attrbutes from the range */
413 remove_child_attr(elem
, wszFont
, &size_str
);
414 nsISelection_SelectAllChildren(nsselection
, (nsIDOMNode
*)elem
);
417 nsIDOMRange_Release(range
);
418 nsIDOMElement_Release(elem
);
420 nsAString_Finish(&font_str
);
421 nsAString_Finish(&size_str
);
422 nsAString_Finish(&val_str
);
424 nsISelection_Release(nsselection
);
425 nsIDOMDocument_Release(nsdoc
);
428 static BOOL
is_visible_text_node(nsIDOMNode
*node
)
430 nsIDOMCharacterData
*char_data
;
435 nsIDOMNode_QueryInterface(node
, &IID_nsIDOMCharacterData
, (void**)&char_data
);
437 nsIDOMCharacterData_GetLength(char_data
, &len
);
439 nsAString_Init(&data_str
, NULL
);
440 nsIDOMCharacterData_GetData(char_data
, &data_str
);
441 nsAString_GetData(&data_str
, &data
, NULL
);
445 for(ptr
=data
+1; ptr
&& isspaceW(*ptr
); ptr
++)
449 nsAString_Finish(&data_str
);
451 nsIDOMCharacterData_Release(char_data
);
456 static nsIDOMNode
*get_child_text_node(nsIDOMNode
*node
, BOOL first
)
458 nsIDOMNode
*iter
, *iter2
;
461 nsIDOMNode_GetFirstChild(node
, &iter
);
463 nsIDOMNode_GetLastChild(node
, &iter
);
468 nsIDOMNode_GetNodeType(iter
, &node_type
);
471 if(is_visible_text_node(iter
))
474 iter2
= get_child_text_node(iter
, first
);
476 nsIDOMNode_Release(iter
);
482 nsIDOMNode_GetNextSibling(iter
, &iter2
);
484 nsIDOMNode_GetPreviousSibling(iter
, &iter2
);
486 nsIDOMNode_Release(iter
);
493 static void handle_arrow_key(HTMLDocument
*This
, nsIDOMKeyEvent
*event
, const char * const cmds
[4])
498 nsIDOMKeyEvent_GetCtrlKey(event
, &b
);
502 nsIDOMKeyEvent_GetShiftKey(event
, &b
);
507 do_ns_editor_command(This
->nscontainer
, cmds
[i
]);
509 nsIDOMKeyEvent_PreventDefault(event
);
512 void handle_edit_event(HTMLDocument
*This
, nsIDOMEvent
*event
)
514 nsIDOMKeyEvent
*key_event
;
517 nsIDOMEvent_QueryInterface(event
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
519 nsIDOMKeyEvent_GetKeyCode(key_event
, &code
);
523 static const char * const cmds
[] = {
526 NSCMD_SELECTCHARPREVIOUS
,
527 NSCMD_SELECTWORDPREVIOUS
531 handle_arrow_key(This
, key_event
, cmds
);
535 static const char * const cmds
[] = {
538 NSCMD_SELECTCHARNEXT
,
543 handle_arrow_key(This
, key_event
, cmds
);
547 static const char * const cmds
[] = {
550 NSCMD_SELECTLINEPREVIOUS
,
555 handle_arrow_key(This
, key_event
, cmds
);
559 static const char * const cmds
[] = {
562 NSCMD_SELECTLINENEXT
,
567 handle_arrow_key(This
, key_event
, cmds
);
570 case DOM_VK_DELETE
: {
571 static const char * const cmds
[] = {
572 NSCMD_DELETECHARFORWARD
,
573 NSCMD_DELETEWORDFORWARD
,
578 handle_arrow_key(This
, key_event
, cmds
);
582 static const char * const cmds
[] = {
585 NSCMD_SELECTBEGINLINE
,
590 handle_arrow_key(This
, key_event
, cmds
);
594 static const char * const cmds
[] = {
602 handle_arrow_key(This
, key_event
, cmds
);
607 nsIDOMKeyEvent_Release(key_event
);
610 void handle_edit_load(HTMLDocument
*This
)
612 get_editor_controller(This
->nscontainer
);
614 if(This
->ui_active
) {
615 OLECHAR wszHTMLDocument
[30];
619 IOleInPlaceUIWindow_SetActiveObject(This
->ip_window
, NULL
, NULL
);
621 IDocHostUIHandler_HideUI(This
->hostui
);
624 IDocHostUIHandler_ShowUI(This
->hostui
, DOCHOSTUITYPE_AUTHOR
, ACTOBJ(This
), CMDTARGET(This
),
625 This
->frame
, This
->ip_window
);
627 LoadStringW(hInst
, IDS_HTMLDOCUMENT
, wszHTMLDocument
,
628 sizeof(wszHTMLDocument
)/sizeof(WCHAR
));
631 IOleInPlaceUIWindow_SetActiveObject(This
->ip_window
, ACTOBJ(This
), wszHTMLDocument
);
633 memset(&rcBorderWidths
, 0, sizeof(rcBorderWidths
));
634 IOleInPlaceFrame_SetBorderSpace(This
->frame
, &rcBorderWidths
);
638 static void set_ns_fontname(NSContainer
*This
, const char *fontname
)
640 nsICommandParams
*nsparam
= create_nscommand_params();
642 nsICommandParams_SetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, fontname
);
643 do_ns_command(This
, NSCMD_FONTFACE
, nsparam
);
644 nsICommandParams_Release(nsparam
);
647 static HRESULT
exec_delete(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
649 TRACE("(%p)->(%p %p)\n", This
, in
, out
);
651 if(This
->nscontainer
)
652 do_ns_editor_command(This
->nscontainer
, NSCMD_DELETECHARFORWARD
);
654 update_doc(This
, UPDATE_UI
);
658 static HRESULT
exec_fontname(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
660 TRACE("(%p)->(%p %p)\n", This
, in
, out
);
662 if(!This
->nscontainer
) {
663 update_doc(This
, UPDATE_UI
);
671 if(V_VT(in
) != VT_BSTR
) {
672 FIXME("Unsupported vt=%d\n", V_VT(out
));
676 TRACE("%s\n", debugstr_w(V_BSTR(in
)));
678 len
= WideCharToMultiByte(CP_ACP
, 0, V_BSTR(in
), -1, NULL
, 0, NULL
, NULL
);
679 stra
= mshtml_alloc(len
);
680 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(in
), -1, stra
, -1, NULL
, NULL
);
682 set_ns_fontname(This
->nscontainer
, stra
);
686 update_doc(This
, UPDATE_UI
);
690 nsICommandParams
*nsparam
;
696 nsparam
= create_nscommand_params();
698 nsres
= get_ns_command_state(This
->nscontainer
, NSCMD_FONTFACE
, nsparam
);
702 nsICommandParams_GetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, &stra
);
703 nsICommandParams_Release(nsparam
);
705 len
= MultiByteToWideChar(CP_ACP
, 0, stra
, -1, NULL
, 0);
706 strw
= mshtml_alloc(len
*sizeof(WCHAR
));
707 MultiByteToWideChar(CP_ACP
, 0, stra
, -1, strw
, -1);
711 V_BSTR(out
) = SysAllocString(strw
);
718 static HRESULT
exec_forecolor(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
720 TRACE("(%p)->(%p %p)\n", This
, in
, out
);
723 if(V_VT(in
) == VT_I4
) {
724 nsICommandParams
*nsparam
= create_nscommand_params();
727 sprintf(color_str
, "#%02x%02x%02x",
728 V_I4(in
)&0xff, (V_I4(in
)>>8)&0xff, (V_I4(in
)>>16)&0xff);
730 nsICommandParams_SetCStringValue(nsparam
, NSSTATE_ATTRIBUTE
, color_str
);
731 do_ns_command(This
->nscontainer
, NSCMD_FONTCOLOR
, nsparam
);
733 nsICommandParams_Release(nsparam
);
735 FIXME("unsupported in vt=%d\n", V_VT(in
));
738 update_doc(This
, UPDATE_UI
);
742 FIXME("unsupported out\n");
749 static HRESULT
exec_fontsize(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
751 TRACE("(%p)->(%p %p)\n", This
, in
, out
);
756 get_font_size(This
, val
);
758 V_I4(out
) = strtolW(val
, NULL
, 10);
765 static const WCHAR format
[] = {'%','d',0};
766 wsprintfW(size
, format
, V_I4(in
));
767 set_font_size(This
, size
);
771 set_font_size(This
, V_BSTR(in
));
774 FIXME("unsupported vt %d\n", V_VT(in
));
777 update_doc(This
, UPDATE_UI
);
783 static HRESULT
exec_selectall(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
785 TRACE("(%p)\n", This
);
788 FIXME("unsupported args\n");
790 if(This
->nscontainer
)
791 do_ns_command(This
->nscontainer
, NSCMD_SELECTALL
, NULL
);
793 update_doc(This
, UPDATE_UI
);
797 static HRESULT
exec_bold(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
799 TRACE("(%p)\n", This
);
802 FIXME("unsupported args\n");
804 if(This
->nscontainer
)
805 do_ns_command(This
->nscontainer
, NSCMD_BOLD
, NULL
);
807 update_doc(This
, UPDATE_UI
);
811 static HRESULT
exec_italic(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
813 TRACE("(%p)\n", This
);
816 FIXME("unsupported args\n");
818 if(This
->nscontainer
)
819 do_ns_command(This
->nscontainer
, NSCMD_ITALIC
, NULL
);
821 update_doc(This
, UPDATE_UI
);
825 static HRESULT
query_justify(HTMLDocument
*This
, OLECMD
*cmd
)
828 case IDM_JUSTIFYCENTER
:
829 TRACE("(%p) IDM_JUSTIFYCENTER\n", This
);
830 cmd
->cmdf
= query_align_status(This
, NSALIGN_CENTER
);
832 case IDM_JUSTIFYLEFT
:
833 TRACE("(%p) IDM_JUSTIFYLEFT\n", This
);
834 /* FIXME: We should set OLECMDF_LATCHED only if it's set explicitly. */
835 if(This
->usermode
!= EDITMODE
|| This
->readystate
< READYSTATE_INTERACTIVE
)
836 cmd
->cmdf
= OLECMDF_SUPPORTED
;
838 cmd
->cmdf
= OLECMDF_SUPPORTED
| OLECMDF_ENABLED
;
840 case IDM_JUSTIFYRIGHT
:
841 TRACE("(%p) IDM_JUSTIFYRIGHT\n", This
);
842 cmd
->cmdf
= query_align_status(This
, NSALIGN_RIGHT
);
849 static HRESULT
exec_justifycenter(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
851 TRACE("(%p)\n", This
);
854 FIXME("unsupported args\n");
856 set_ns_align(This
, NSALIGN_CENTER
);
857 update_doc(This
, UPDATE_UI
);
861 static HRESULT
exec_justifyleft(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
863 TRACE("(%p)\n", This
);
866 FIXME("unsupported args\n");
868 set_ns_align(This
, NSALIGN_LEFT
);
869 update_doc(This
, UPDATE_UI
);
873 static HRESULT
exec_justifyright(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
875 TRACE("(%p)\n", This
);
878 FIXME("unsupported args\n");
880 set_ns_align(This
, NSALIGN_RIGHT
);
881 update_doc(This
, UPDATE_UI
);
885 static HRESULT
exec_underline(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
887 TRACE("(%p)\n", This
);
890 FIXME("unsupported args\n");
892 if(This
->nscontainer
)
893 do_ns_command(This
->nscontainer
, NSCMD_UNDERLINE
, NULL
);
895 update_doc(This
, UPDATE_UI
);
899 static HRESULT
exec_horizontalline(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
901 TRACE("(%p)\n", This
);
904 FIXME("unsupported args\n");
906 if(This
->nscontainer
)
907 do_ns_command(This
->nscontainer
, NSCMD_INSERTHR
, NULL
);
909 update_doc(This
, UPDATE_UI
);
913 static HRESULT
exec_orderlist(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
915 TRACE("(%p)\n", This
);
918 FIXME("unsupported args\n");
920 if(This
->nscontainer
)
921 do_ns_command(This
->nscontainer
, NSCMD_OL
, NULL
);
923 update_doc(This
, UPDATE_UI
);
927 static HRESULT
exec_unorderlist(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
929 TRACE("(%p)\n", This
);
932 FIXME("unsupported args\n");
934 if(This
->nscontainer
)
935 do_ns_command(This
->nscontainer
, NSCMD_UL
, NULL
);
937 update_doc(This
, UPDATE_UI
);
941 static HRESULT
exec_indent(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
943 TRACE("(%p)\n", This
);
946 FIXME("unsupported args\n");
948 if(This
->nscontainer
)
949 do_ns_command(This
->nscontainer
, NSCMD_INDENT
, NULL
);
951 update_doc(This
, UPDATE_UI
);
955 static HRESULT
exec_outdent(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
957 TRACE("(%p)\n", This
);
960 FIXME("unsupported args\n");
962 if(This
->nscontainer
)
963 do_ns_command(This
->nscontainer
, NSCMD_OUTDENT
, NULL
);
965 update_doc(This
, UPDATE_UI
);
969 static HRESULT
exec_composesettings(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
973 if(out
|| !in
|| V_VT(in
) != VT_BSTR
) {
974 WARN("invalid arg\n");
978 TRACE("(%p)->(%x %s)\n", This
, cmdexecopt
, debugstr_w(V_BSTR(in
)));
980 update_doc(This
, UPDATE_UI
);
984 exec_bold(This
, cmdexecopt
, NULL
, NULL
);
985 ptr
= strchrW(ptr
, ',');
990 exec_italic(This
, cmdexecopt
, NULL
, NULL
);
991 ptr
= strchrW(ptr
, ',');
996 exec_underline(This
, cmdexecopt
, NULL
, NULL
);
997 ptr
= strchrW(ptr
, ',');
1001 if(isdigitW(*++ptr
)) {
1005 V_I4(&v
) = *ptr
-'0';
1007 exec_fontsize(This
, cmdexecopt
, &v
, NULL
);
1009 ptr
= strchrW(ptr
, ',');
1014 FIXME("set font color\n");
1015 ptr
= strchrW(ptr
, ',');
1020 FIXME("set background color\n");
1021 ptr
= strchrW(ptr
, ',');
1030 V_BSTR(&v
) = SysAllocString(ptr
);
1032 exec_fontname(This
, cmdexecopt
, &v
, NULL
);
1034 SysFreeString(V_BSTR(&v
));
1040 HRESULT
editor_exec_copy(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
1042 update_doc(This
, UPDATE_UI
);
1044 if(!This
->nscontainer
)
1047 do_ns_editor_command(This
->nscontainer
, NSCMD_COPY
);
1051 HRESULT
editor_exec_cut(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
1053 update_doc(This
, UPDATE_UI
);
1055 if(!This
->nscontainer
)
1058 do_ns_editor_command(This
->nscontainer
, NSCMD_CUT
);
1062 HRESULT
editor_exec_paste(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
1064 update_doc(This
, UPDATE_UI
);
1066 if(!This
->nscontainer
)
1069 do_ns_editor_command(This
->nscontainer
, NSCMD_PASTE
);
1073 static HRESULT
query_edit_status(HTMLDocument
*This
, OLECMD
*cmd
)
1075 switch(cmd
->cmdID
) {
1077 TRACE("CGID_MSHTML: IDM_DELETE\n");
1078 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1081 TRACE("CGID_MSHTML: IDM_FONTNAME\n");
1082 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1085 TRACE("CGID_MSHTML: IDM_FONTSIZE\n");
1086 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1089 TRACE("CGID_MSHTML: IDM_BOLD\n");
1090 cmd
->cmdf
= query_ns_edit_status(This
, NSCMD_BOLD
);
1093 TRACE("CGID_MSHTML: IDM_FORECOLOR\n");
1094 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1097 TRACE("CGID_MSHTML: IDM_ITALIC\n");
1098 cmd
->cmdf
= query_ns_edit_status(This
, NSCMD_ITALIC
);
1101 TRACE("CGID_MSHTML: IDM_UNDERLINE\n");
1102 cmd
->cmdf
= query_ns_edit_status(This
, NSCMD_UNDERLINE
);
1104 case IDM_HORIZONTALLINE
:
1105 TRACE("CGID_MSHTML: IDM_HORIZONTALLINE\n");
1106 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1109 TRACE("CGID_MSHTML: IDM_ORDERLIST\n");
1110 cmd
->cmdf
= query_ns_edit_status(This
, NSCMD_OL
);
1112 case IDM_UNORDERLIST
:
1113 TRACE("CGID_MSHTML: IDM_HORIZONTALLINE\n");
1114 cmd
->cmdf
= query_ns_edit_status(This
, NSCMD_UL
);
1117 TRACE("CGID_MSHTML: IDM_INDENT\n");
1118 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1121 TRACE("CGID_MSHTML: IDM_OUTDENT\n");
1122 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1125 TRACE("CGID_MSHTML: IDM_HYPERLINK\n");
1126 cmd
->cmdf
= query_ns_edit_status(This
, NULL
);
1133 static INT_PTR CALLBACK
hyperlink_dlgproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1135 static const WCHAR wszOther
[] = {'(','o','t','h','e','r',')',0};
1141 static const WCHAR wszFile
[] = {'f','i','l','e',':',0};
1142 static const WCHAR wszFtp
[] = {'f','t','p',':',0};
1143 static const WCHAR wszHttp
[] = {'h','t','t','p',':',0};
1144 static const WCHAR wszHttps
[] = {'h','t','t','p','s',':',0};
1145 static const WCHAR wszMailto
[] = {'m','a','i','l','t','o',':',0};
1146 static const WCHAR wszNews
[] = {'n','e','w','s',':',0};
1148 HWND hwndCB
= GetDlgItem(hwnd
, IDC_TYPE
);
1149 HWND hwndURL
= GetDlgItem(hwnd
, IDC_URL
);
1152 SetWindowLongPtrW(hwnd
, DWLP_USER
, lparam
);
1154 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszOther
);
1155 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszFile
);
1156 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszFtp
);
1157 def_idx
= SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszHttp
);
1158 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszHttps
);
1159 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszMailto
);
1160 SendMessageW(hwndCB
, CB_INSERTSTRING
, -1, (LPARAM
)wszNews
);
1161 SendMessageW(hwndCB
, CB_SETCURSEL
, def_idx
, 0);
1163 /* force the updating of the URL edit box */
1164 SendMessageW(hwnd
, WM_COMMAND
, MAKEWPARAM(IDC_TYPE
, CBN_SELCHANGE
), (LPARAM
)hwndCB
);
1167 len
= SendMessageW(hwndURL
, WM_GETTEXTLENGTH
, 0, 0);
1168 SendMessageW(hwndURL
, EM_SETSEL
, 0, len
);
1175 case MAKEWPARAM(IDCANCEL
, BN_CLICKED
):
1176 EndDialog(hwnd
, wparam
);
1178 case MAKEWPARAM(IDOK
, BN_CLICKED
):
1180 BSTR
*url
= (BSTR
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1181 HWND hwndURL
= GetDlgItem(hwnd
, IDC_URL
);
1182 INT len
= GetWindowTextLengthW(hwndURL
);
1183 *url
= SysAllocStringLen(NULL
, len
+ 1);
1184 GetWindowTextW(hwndURL
, *url
, len
+ 1);
1185 EndDialog(hwnd
, wparam
);
1188 case MAKEWPARAM(IDC_TYPE
, CBN_SELCHANGE
):
1190 HWND hwndURL
= GetDlgItem(hwnd
, IDC_URL
);
1196 static const WCHAR wszSlashSlash
[] = {'/','/'};
1198 /* get string of currently selected hyperlink type */
1199 item
= SendMessageW((HWND
)lparam
, CB_GETCURSEL
, 0, 0);
1200 len
= SendMessageW((HWND
)lparam
, CB_GETLBTEXTLEN
, item
, 0);
1201 type
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
1202 SendMessageW((HWND
)lparam
, CB_GETLBTEXT
, item
, (LPARAM
)type
);
1204 if (!strcmpW(type
, wszOther
))
1207 /* get current URL */
1208 len
= GetWindowTextLengthW(hwndURL
);
1209 url
= HeapAlloc(GetProcessHeap(), 0, (len
+ strlenW(type
) + 3) * sizeof(WCHAR
));
1210 GetWindowTextW(hwndURL
, url
, len
+ 1);
1212 /* strip off old protocol */
1213 p
= strchrW(url
, ':');
1214 if (p
&& p
[1] == '/' && p
[2] == '/')
1217 memmove(url
+ (*type
!= '\0' ? strlenW(type
) + 2 : 0), p
, (len
+ 1 - (p
- url
)) * sizeof(WCHAR
));
1219 /* add new protocol */
1222 memcpy(url
, type
, strlenW(type
) * sizeof(WCHAR
));
1223 memcpy(url
+ strlenW(type
), wszSlashSlash
, sizeof(wszSlashSlash
));
1226 SetWindowTextW(hwndURL
, url
);
1228 HeapFree(GetProcessHeap(), 0, url
);
1229 HeapFree(GetProcessHeap(), 0, type
);
1235 EndDialog(hwnd
, IDCANCEL
);
1242 static HRESULT
exec_hyperlink(HTMLDocument
*This
, DWORD cmdexecopt
, VARIANT
*in
, VARIANT
*out
)
1247 PRBool insert_link_at_caret
;
1248 nsISelection
*nsselection
;
1250 FIXME("%p, 0x%x, %p, %p\n", This
, cmdexecopt
, in
, out
);
1252 if (cmdexecopt
== OLECMDEXECOPT_DONTPROMPTUSER
)
1254 if (!in
|| V_VT(in
) != VT_BSTR
)
1256 WARN("invalid arg\n");
1257 return E_INVALIDARG
;
1263 ret
= DialogBoxParamW(hInst
, MAKEINTRESOURCEW(IDD_HYPERLINK
), NULL
/* FIXME */, hyperlink_dlgproc
, (LPARAM
)&url
);
1265 return OLECMDERR_E_CANCELED
;
1268 nsselection
= get_ns_selection(This
);
1272 nsAString_Init(&ns_url
, url
);
1274 nsISelection_GetIsCollapsed(nsselection
, &insert_link_at_caret
);
1276 if (insert_link_at_caret
)
1278 static const WCHAR wszA
[] = {'a',0};
1279 static const WCHAR wszHref
[] = {'h','r','e','f',0};
1280 nsIHTMLEditor
*html_editor
;
1281 nsIDOMDocument
*nsdoc
;
1282 nsIDOMNode
*text_node
;
1283 nsIDOMElement
*anchor_elem
;
1284 nsIDOMNode
*unused_node
;
1289 nsres
= nsIWebNavigation_GetDocument(This
->nscontainer
->navigation
, &nsdoc
);
1290 if(NS_FAILED(nsres
))
1293 nsAString_Init(&a_str
, wszA
);
1294 nsAString_Init(&href_str
, wszHref
);
1296 /* create an element for the link */
1297 nsIDOMDocument_CreateElement(nsdoc
, &a_str
, &anchor_elem
);
1298 nsIDOMElement_SetAttribute(anchor_elem
, &href_str
, &ns_url
);
1300 nsAString_Finish(&href_str
);
1301 nsAString_Finish(&a_str
);
1303 /* create an element with text of URL */
1304 nsIDOMDocument_CreateTextNode(nsdoc
, &ns_url
, (nsIDOMText
**)&text_node
);
1306 /* wrap the <a> tags around the text element */
1307 nsIDOMElement_AppendChild(anchor_elem
, text_node
, &unused_node
);
1308 nsIDOMNode_Release(text_node
);
1309 nsIDOMNode_Release(unused_node
);
1311 nsIEditor_QueryInterface(This
->nscontainer
->editor
, &IID_nsIHTMLEditor
, (void **)&html_editor
);
1314 /* add them to the document at the caret position */
1315 nsres
= nsIHTMLEditor_InsertElementAtSelection(html_editor
, anchor_elem
, FALSE
);
1316 nsIHTMLEditor_Release(html_editor
);
1319 nsISelection_SelectAllChildren(nsselection
, (nsIDOMNode
*)anchor_elem
);
1321 nsIDOMElement_Release(anchor_elem
);
1322 nsIDOMDocument_Release(nsdoc
);
1326 nsICommandParams
*nsparam
= create_nscommand_params();
1328 nsICommandParams_SetStringValue(nsparam
, NSSTATE_ATTRIBUTE
, &ns_url
);
1329 do_ns_command(This
->nscontainer
, NSCMD_INSERTLINKNOUI
, nsparam
);
1330 nsICommandParams_Release(nsparam
);
1333 nsAString_Finish(&ns_url
);
1335 nsISelection_Release(nsselection
);
1337 if (cmdexecopt
!= OLECMDEXECOPT_DONTPROMPTUSER
)
1343 static HRESULT
query_selall_status(HTMLDocument
*This
, OLECMD
*cmd
)
1345 TRACE("(%p)->(%p)\n", This
, cmd
);
1347 cmd
->cmdf
= OLECMDF_SUPPORTED
|OLECMDF_ENABLED
;
1351 const cmdtable_t editmode_cmds
[] = {
1352 {IDM_DELETE
, query_edit_status
, exec_delete
},
1353 {IDM_FONTNAME
, query_edit_status
, exec_fontname
},
1354 {IDM_FONTSIZE
, query_edit_status
, exec_fontsize
},
1355 {IDM_SELECTALL
, query_selall_status
, exec_selectall
},
1356 {IDM_FORECOLOR
, query_edit_status
, exec_forecolor
},
1357 {IDM_BOLD
, query_edit_status
, exec_bold
},
1358 {IDM_ITALIC
, query_edit_status
, exec_italic
},
1359 {IDM_JUSTIFYCENTER
, query_justify
, exec_justifycenter
},
1360 {IDM_JUSTIFYRIGHT
, query_justify
, exec_justifyright
},
1361 {IDM_JUSTIFYLEFT
, query_justify
, exec_justifyleft
},
1362 {IDM_UNDERLINE
, query_edit_status
, exec_underline
},
1363 {IDM_HORIZONTALLINE
, query_edit_status
, exec_horizontalline
},
1364 {IDM_ORDERLIST
, query_edit_status
, exec_orderlist
},
1365 {IDM_UNORDERLIST
, query_edit_status
, exec_unorderlist
},
1366 {IDM_INDENT
, query_edit_status
, exec_indent
},
1367 {IDM_OUTDENT
, query_edit_status
, exec_outdent
},
1368 {IDM_COMPOSESETTINGS
, NULL
, exec_composesettings
},
1369 {IDM_HYPERLINK
, query_edit_status
, exec_hyperlink
},
1373 void init_editor(HTMLDocument
*This
)
1375 update_doc(This
, UPDATE_UI
);
1377 if(!This
->nscontainer
)
1380 set_ns_fontname(This
->nscontainer
, "Times New Roman");
1383 HRESULT
editor_is_dirty(HTMLDocument
*This
)
1387 if(!This
->nscontainer
|| !This
->nscontainer
->editor
)
1390 nsIEditor_GetDocumentModified(This
->nscontainer
->editor
, &modified
);
1392 return modified
? S_OK
: S_FALSE
;