mshtml: Added IDM_COPY in browse mode implementation.
[wine/multimedia.git] / dlls / mshtml / olecmd.c
blob458209c3cbe6e7ff1a197567089ba4eec659bc8b
1 /*
2 * Copyright 2005-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
19 #include "config.h"
21 #include <stdarg.h>
22 #include <stdio.h>
24 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "ole2.h"
31 #include "shlguid.h"
32 #include "mshtmdid.h"
33 #include "idispids.h"
34 #include "mshtmcid.h"
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
39 #include "mshtml_private.h"
40 #include "resource.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
44 #define NSCMD_BOLD "cmd_bold"
45 #define NSCMD_COPY "cmd_copy"
46 #define NSCMD_ITALIC "cmd_italic"
47 #define NSCMD_UNDERLINE "cmd_underline"
48 #define NSCMD_ALIGN "cmd_align"
49 #define NSCMD_INDENT "cmd_indent"
50 #define NSCMD_OUTDENT "cmd_outdent"
51 #define NSCMD_INSERTHR "cmd_insertHR"
52 #define NSCMD_UL "cmd_ul"
53 #define NSCMD_OL "cmd_ol"
55 #define NSSTATE_ATTRIBUTE "state_attribute"
57 #define NSALIGN_CENTER "center"
58 #define NSALIGN_LEFT "left"
59 #define NSALIGN_RIGHT "right"
61 void do_ns_command(NSContainer *This, const char *cmd, nsICommandParams *nsparam)
63 nsICommandManager *cmdmgr;
64 nsIInterfaceRequestor *iface_req;
65 nsresult nsres;
67 TRACE("(%p)\n", This);
69 nsres = nsIWebBrowser_QueryInterface(This->webbrowser,
70 &IID_nsIInterfaceRequestor, (void**)&iface_req);
71 if(NS_FAILED(nsres)) {
72 ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres);
73 return;
76 nsres = nsIInterfaceRequestor_GetInterface(iface_req, &IID_nsICommandManager,
77 (void**)&cmdmgr);
78 nsIInterfaceRequestor_Release(iface_req);
79 if(NS_FAILED(nsres)) {
80 ERR("Could not get nsICommandManager: %08x\n", nsres);
81 return;
84 nsres = nsICommandManager_DoCommand(cmdmgr, cmd, nsparam, NULL);
85 if(NS_FAILED(nsres))
86 ERR("DoCommand(%s) failed: %08x\n", debugstr_a(cmd), nsres);
88 nsICommandManager_Release(cmdmgr);
91 /**********************************************************
92 * IOleCommandTarget implementation
95 #define CMDTARGET_THIS(iface) DEFINE_THIS(HTMLDocument, OleCommandTarget, iface)
97 static HRESULT exec_open(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
99 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
100 return E_NOTIMPL;
103 static HRESULT exec_new(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
105 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
106 return E_NOTIMPL;
109 static HRESULT exec_save(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
111 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
112 return E_NOTIMPL;
115 static HRESULT exec_save_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
117 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
118 return E_NOTIMPL;
121 static HRESULT exec_save_copy_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
123 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
124 return E_NOTIMPL;
127 static nsresult set_head_text(nsIPrintSettings *settings, LPCWSTR template, BOOL head, int pos)
129 if(head) {
130 switch(pos) {
131 case 0:
132 return nsIPrintSettings_SetHeaderStrLeft(settings, template);
133 case 1:
134 return nsIPrintSettings_SetHeaderStrRight(settings, template);
135 case 2:
136 return nsIPrintSettings_SetHeaderStrCenter(settings, template);
138 }else {
139 switch(pos) {
140 case 0:
141 return nsIPrintSettings_SetFooterStrLeft(settings, template);
142 case 1:
143 return nsIPrintSettings_SetFooterStrRight(settings, template);
144 case 2:
145 return nsIPrintSettings_SetFooterStrCenter(settings, template);
149 return NS_OK;
152 static void set_print_template(nsIPrintSettings *settings, LPCWSTR template, BOOL head)
154 PRUnichar nstemplate[200]; /* FIXME: Use dynamic allocation */
155 PRUnichar *p = nstemplate;
156 LPCWSTR ptr=template;
157 int pos=0;
159 while(*ptr) {
160 if(*ptr != '&') {
161 *p++ = *ptr++;
162 continue;
165 switch(*++ptr) {
166 case '&':
167 *p++ = '&';
168 *p++ = '&';
169 ptr++;
170 break;
171 case 'b': /* change align */
172 ptr++;
173 *p = 0;
174 set_head_text(settings, nstemplate, head, pos);
175 p = nstemplate;
176 pos++;
177 break;
178 case 'd': { /* short date */
179 SYSTEMTIME systime;
180 GetLocalTime(&systime);
181 GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &systime, NULL, p,
182 sizeof(nstemplate)-(p-nstemplate)*sizeof(WCHAR));
183 p += strlenW(p);
184 ptr++;
185 break;
187 case 'p': /* page number */
188 *p++ = '&';
189 *p++ = 'P';
190 ptr++;
191 break;
192 case 'P': /* page count */
193 *p++ = '?'; /* FIXME */
194 ptr++;
195 break;
196 case 'u':
197 *p++ = '&';
198 *p++ = 'U';
199 ptr++;
200 break;
201 case 'w':
202 /* FIXME: set window title */
203 ptr++;
204 break;
205 default:
206 *p++ = '&';
207 *p++ = *ptr++;
211 *p = 0;
212 set_head_text(settings, nstemplate, head, pos);
214 while(++pos < 3)
215 set_head_text(settings, p, head, pos);
218 static void set_default_templates(nsIPrintSettings *settings)
220 WCHAR buf[64];
222 static const PRUnichar empty[] = {0};
224 nsIPrintSettings_SetHeaderStrLeft(settings, empty);
225 nsIPrintSettings_SetHeaderStrRight(settings, empty);
226 nsIPrintSettings_SetHeaderStrCenter(settings, empty);
227 nsIPrintSettings_SetFooterStrLeft(settings, empty);
228 nsIPrintSettings_SetFooterStrRight(settings, empty);
229 nsIPrintSettings_SetFooterStrCenter(settings, empty);
231 if(LoadStringW(get_shdoclc(), IDS_PRINT_HEADER_TEMPLATE, buf,
232 sizeof(buf)/sizeof(WCHAR)))
233 set_print_template(settings, buf, TRUE);
236 if(LoadStringW(get_shdoclc(), IDS_PRINT_FOOTER_TEMPLATE, buf,
237 sizeof(buf)/sizeof(WCHAR)))
238 set_print_template(settings, buf, FALSE);
242 static HRESULT exec_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
244 nsIInterfaceRequestor *iface_req;
245 nsIWebBrowserPrint *nsprint;
246 nsIPrintSettings *settings;
247 nsresult nsres;
249 TRACE("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
251 if(pvaOut)
252 FIXME("unsupported pvaOut\n");
254 if(!This->nscontainer)
255 return S_OK;
257 nsres = nsIWebBrowser_QueryInterface(This->nscontainer->webbrowser,
258 &IID_nsIInterfaceRequestor, (void**)&iface_req);
259 if(NS_FAILED(nsres)) {
260 ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres);
261 return S_OK;
264 nsres = nsIInterfaceRequestor_GetInterface(iface_req, &IID_nsIWebBrowserPrint,
265 (void**)&nsprint);
266 nsIInterfaceRequestor_Release(iface_req);
267 if(NS_FAILED(nsres)) {
268 ERR("Could not get nsIWebBrowserPrint: %08x\n", nsres);
269 return S_OK;
272 nsres = nsIWebBrowserPrint_GetGlobalPrintSettings(nsprint, &settings);
273 if(NS_FAILED(nsres))
274 ERR("GetCurrentPrintSettings failed: %08x\n", nsres);
276 set_default_templates(settings);
278 if(pvaIn) {
279 switch(V_VT(pvaIn)) {
280 case VT_BYREF|VT_ARRAY: {
281 VARIANT *opts;
282 DWORD opts_cnt;
284 if(V_ARRAY(pvaIn)->cDims != 1)
285 WARN("cDims = %d\n", V_ARRAY(pvaIn)->cDims);
287 SafeArrayAccessData(V_ARRAY(pvaIn), (void**)&opts);
288 opts_cnt = V_ARRAY(pvaIn)->rgsabound[0].cElements;
290 if(opts_cnt >= 1) {
291 switch(V_VT(opts)) {
292 case VT_BSTR:
293 TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts)));
294 set_print_template(settings, V_BSTR(opts), TRUE);
295 break;
296 case VT_NULL:
297 break;
298 default:
299 WARN("V_VT(opts) = %d\n", V_VT(opts));
303 if(opts_cnt >= 2) {
304 switch(V_VT(opts+1)) {
305 case VT_BSTR:
306 TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts+1)));
307 set_print_template(settings, V_BSTR(opts+1), FALSE);
308 break;
309 case VT_NULL:
310 break;
311 default:
312 WARN("V_VT(opts) = %d\n", V_VT(opts+1));
316 if(opts_cnt >= 3)
317 FIXME("Unsupported opts_cnt %d\n", opts_cnt);
319 SafeArrayUnaccessData(V_ARRAY(pvaIn));
320 break;
322 default:
323 FIXME("unsupported vt %x\n", V_VT(pvaIn));
327 nsres = nsIWebBrowserPrint_Print(nsprint, settings, NULL);
328 if(NS_FAILED(nsres))
329 ERR("Print failed: %08x\n", nsres);
331 nsIWebBrowserPrint_Release(nsprint);
333 return S_OK;
336 static HRESULT exec_print_preview(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
338 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
339 return E_NOTIMPL;
342 static HRESULT exec_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
344 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
345 return E_NOTIMPL;
348 static HRESULT exec_spell(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
350 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
351 return E_NOTIMPL;
354 static HRESULT exec_properties(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
356 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
357 return E_NOTIMPL;
360 static HRESULT exec_cut(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
362 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
363 return E_NOTIMPL;
366 static HRESULT exec_copy(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
368 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
369 return E_NOTIMPL;
372 static HRESULT exec_paste(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
374 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
375 return E_NOTIMPL;
378 static HRESULT exec_paste_special(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
380 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
381 return E_NOTIMPL;
384 static HRESULT exec_undo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
386 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
387 return E_NOTIMPL;
390 static HRESULT exec_rendo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
392 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
393 return E_NOTIMPL;
396 static HRESULT exec_select_all(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
398 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
399 return E_NOTIMPL;
402 static HRESULT exec_clear_selection(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
404 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
405 return E_NOTIMPL;
408 static HRESULT exec_zoom(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
410 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
411 return E_NOTIMPL;
414 static HRESULT exec_get_zoom_range(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
416 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
417 return E_NOTIMPL;
420 static HRESULT exec_refresh(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
422 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
423 return E_NOTIMPL;
426 static HRESULT exec_stop(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
428 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
429 return E_NOTIMPL;
432 static HRESULT exec_stop_download(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
434 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
435 return E_NOTIMPL;
438 static HRESULT exec_delete(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
440 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
441 return E_NOTIMPL;
444 static HRESULT exec_enable_interaction(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
446 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
447 return E_NOTIMPL;
450 static HRESULT exec_on_unload(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
452 TRACE("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
454 /* Tests show that we have nothing more to do here */
456 if(pvaOut) {
457 V_VT(pvaOut) = VT_BOOL;
458 V_BOOL(pvaOut) = VARIANT_TRUE;
461 return S_OK;
464 static HRESULT exec_show_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
466 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
467 return E_NOTIMPL;
470 static HRESULT exec_show_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
472 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
473 return E_NOTIMPL;
476 static HRESULT exec_close(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
478 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
479 return E_NOTIMPL;
482 static HRESULT exec_set_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
484 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
485 return E_NOTIMPL;
488 static HRESULT exec_get_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
490 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
491 return E_NOTIMPL;
494 static HRESULT query_mshtml_copy(HTMLDocument *This, OLECMD *cmd)
496 FIXME("(%p)\n", This);
497 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
498 return S_OK;
501 static HRESULT exec_mshtml_copy(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
503 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
505 if(This->usermode == EDITMODE)
506 return editor_exec_copy(This, cmdexecopt, in, out);
508 do_ns_command(This->nscontainer, NSCMD_COPY, NULL);
509 return S_OK;
512 static HRESULT query_mshtml_cut(HTMLDocument *This, OLECMD *cmd)
514 FIXME("(%p)\n", This);
515 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
516 return S_OK;
519 static HRESULT exec_mshtml_cut(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
521 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
523 if(This->usermode == EDITMODE)
524 return editor_exec_cut(This, cmdexecopt, in, out);
526 FIXME("Unimplemented in browse mode\n");
527 return E_NOTIMPL;
530 static HRESULT query_mshtml_paste(HTMLDocument *This, OLECMD *cmd)
532 FIXME("(%p)\n", This);
533 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
534 return S_OK;
537 static HRESULT exec_mshtml_paste(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
539 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
541 if(This->usermode == EDITMODE)
542 return editor_exec_paste(This, cmdexecopt, in, out);
544 FIXME("Unimplemented in browse mode\n");
545 return E_NOTIMPL;
548 static HRESULT exec_browsemode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
550 WARN("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
552 if(in || out)
553 FIXME("unsupported args\n");
555 This->usermode = BROWSEMODE;
557 return S_OK;
560 static HRESULT exec_editmode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
562 IMoniker *mon;
563 HRESULT hres;
565 static const WCHAR wszAboutBlank[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
567 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
569 if(in || out)
570 FIXME("unsupported args\n");
572 if(This->usermode == EDITMODE)
573 return S_OK;
575 This->usermode = EDITMODE;
577 if(This->frame)
578 IOleInPlaceFrame_SetStatusText(This->frame, NULL);
580 if(This->client) {
581 IOleCommandTarget *cmdtrg;
583 hres = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget,
584 (void**)&cmdtrg);
585 if(SUCCEEDED(hres)) {
586 VARIANT var;
588 V_VT(&var) = VT_I4;
589 V_I4(&var) = 0;
590 IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL);
592 IOleCommandTarget_Release(cmdtrg);
596 if(This->hostui) {
597 DOCHOSTUIINFO hostinfo;
599 memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
600 hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
601 hres = IDocHostUIHandler_GetHostInfo(This->hostui, &hostinfo);
602 if(SUCCEEDED(hres))
603 /* FIXME: use hostinfo */
604 TRACE("hostinfo = {%u %08x %08x %s %s}\n",
605 hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
606 debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
609 if(This->nscontainer)
610 set_ns_editmode(This->nscontainer);
612 hres = CreateURLMoniker(NULL, wszAboutBlank, &mon);
613 if(FAILED(hres)) {
614 FIXME("CreateURLMoniker failed: %08x\n", hres);
615 return hres;
618 update_doc(This, UPDATE_UI);
620 return IPersistMoniker_Load(PERSISTMON(This), TRUE, mon, NULL, 0);
623 static HRESULT exec_htmleditmode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
625 FIXME("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
626 return S_OK;
629 static HRESULT exec_setdirty(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
631 FIXME("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
632 return E_NOTIMPL;
635 static HRESULT exec_baselinefont3(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
637 FIXME("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
638 return S_OK;
641 static HRESULT exec_respectvisibility_indesign(HTMLDocument *This, DWORD cmdexecopt,
642 VARIANT *in, VARIANT *out)
644 FIXME("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
645 return E_NOTIMPL;
648 static HRESULT query_enabled_stub(HTMLDocument *This, OLECMD *cmd)
650 switch(cmd->cmdID) {
651 case IDM_PRINT:
652 FIXME("CGID_MSHTML: IDM_PRINT\n");
653 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
654 break;
655 case IDM_BLOCKDIRLTR:
656 FIXME("CGID_MSHTML: IDM_BLOCKDIRLTR\n");
657 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
658 break;
659 case IDM_BLOCKDIRRTL:
660 FIXME("CGID_MSHTML: IDM_BLOCKDIRRTL\n");
661 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
662 break;
665 return S_OK;
668 static const struct {
669 OLECMDF cmdf;
670 HRESULT (*func)(HTMLDocument*,DWORD,VARIANT*,VARIANT*);
671 } exec_table[OLECMDID_GETPRINTTEMPLATE+1] = {
672 {0},
673 { OLECMDF_SUPPORTED, exec_open }, /* OLECMDID_OPEN */
674 { OLECMDF_SUPPORTED, exec_new }, /* OLECMDID_NEW */
675 { OLECMDF_SUPPORTED, exec_save }, /* OLECMDID_SAVE */
676 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_save_as }, /* OLECMDID_SAVEAS */
677 { OLECMDF_SUPPORTED, exec_save_copy_as }, /* OLECMDID_SAVECOPYAS */
678 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_print }, /* OLECMDID_PRINT */
679 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_print_preview }, /* OLECMDID_PRINTPREVIEW */
680 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_page_setup }, /* OLECMDID_PAGESETUP */
681 { OLECMDF_SUPPORTED, exec_spell }, /* OLECMDID_SPELL */
682 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_properties }, /* OLECMDID_PROPERTIES */
683 { OLECMDF_SUPPORTED, exec_cut }, /* OLECMDID_CUT */
684 { OLECMDF_SUPPORTED, exec_copy }, /* OLECMDID_COPY */
685 { OLECMDF_SUPPORTED, exec_paste }, /* OLECMDID_PASTE */
686 { OLECMDF_SUPPORTED, exec_paste_special }, /* OLECMDID_PASTESPECIAL */
687 { OLECMDF_SUPPORTED, exec_undo }, /* OLECMDID_UNDO */
688 { OLECMDF_SUPPORTED, exec_rendo }, /* OLECMDID_REDO */
689 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_select_all }, /* OLECMDID_SELECTALL */
690 { OLECMDF_SUPPORTED, exec_clear_selection }, /* OLECMDID_CLEARSELECTION */
691 { OLECMDF_SUPPORTED, exec_zoom }, /* OLECMDID_ZOOM */
692 { OLECMDF_SUPPORTED, exec_get_zoom_range }, /* OLECMDID_GETZOOMRANGE */
693 {0},
694 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_refresh }, /* OLECMDID_REFRESH */
695 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_stop }, /* OLECMDID_STOP */
696 {0},{0},{0},{0},{0},{0},
697 { OLECMDF_SUPPORTED, exec_stop_download }, /* OLECMDID_STOPDOWNLOAD */
698 {0},{0},
699 { OLECMDF_SUPPORTED, exec_delete }, /* OLECMDID_DELETE */
700 {0},{0},
701 { OLECMDF_SUPPORTED, exec_enable_interaction }, /* OLECMDID_ENABLE_INTERACTION */
702 { OLECMDF_SUPPORTED, exec_on_unload }, /* OLECMDID_ONUNLOAD */
703 {0},{0},{0},{0},{0},
704 { OLECMDF_SUPPORTED, exec_show_page_setup }, /* OLECMDID_SHOWPAGESETUP */
705 { OLECMDF_SUPPORTED, exec_show_print }, /* OLECMDID_SHOWPRINT */
706 {0},{0},
707 { OLECMDF_SUPPORTED, exec_close }, /* OLECMDID_CLOSE */
708 {0},{0},{0},
709 { OLECMDF_SUPPORTED, exec_set_print_template }, /* OLECMDID_SETPRINTTEMPLATE */
710 { OLECMDF_SUPPORTED, exec_get_print_template } /* OLECMDID_GETPRINTTEMPLATE */
713 static const cmdtable_t base_cmds[] = {
714 {IDM_COPY, query_mshtml_copy, exec_mshtml_copy},
715 {IDM_PASTE, query_mshtml_paste, exec_mshtml_paste},
716 {IDM_CUT, query_mshtml_cut, exec_mshtml_cut},
717 {IDM_BROWSEMODE, NULL, exec_browsemode},
718 {IDM_EDITMODE, NULL, exec_editmode},
719 {IDM_PRINT, query_enabled_stub, exec_print},
720 {IDM_SETDIRTY, NULL, exec_setdirty},
721 {IDM_HTMLEDITMODE, NULL, exec_htmleditmode},
722 {IDM_BASELINEFONT3, NULL, exec_baselinefont3},
723 {IDM_BLOCKDIRLTR, query_enabled_stub, NULL},
724 {IDM_BLOCKDIRRTL, query_enabled_stub, NULL},
725 {IDM_RESPECTVISIBILITY_INDESIGN, NULL, exec_respectvisibility_indesign},
726 {0,NULL,NULL}
729 static HRESULT WINAPI OleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
731 HTMLDocument *This = CMDTARGET_THIS(iface);
732 return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
735 static ULONG WINAPI OleCommandTarget_AddRef(IOleCommandTarget *iface)
737 HTMLDocument *This = CMDTARGET_THIS(iface);
738 return IHTMLDocument2_AddRef(HTMLDOC(This));
741 static ULONG WINAPI OleCommandTarget_Release(IOleCommandTarget *iface)
743 HTMLDocument *This = CMDTARGET_THIS(iface);
744 return IHTMLDocument_Release(HTMLDOC(This));
747 static HRESULT query_from_table(HTMLDocument *This, const cmdtable_t *cmdtable, OLECMD *cmd)
749 const cmdtable_t *iter = cmdtable;
751 cmd->cmdf = 0;
753 while(iter->id && iter->id != cmd->cmdID)
754 iter++;
756 if(!iter->id || !iter->query)
757 return OLECMDERR_E_NOTSUPPORTED;
759 return iter->query(This, cmd);
762 static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
763 ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
765 HTMLDocument *This = CMDTARGET_THIS(iface);
766 HRESULT hres = S_OK, hr;
768 TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
770 if(!pguidCmdGroup) {
771 ULONG i;
773 for(i=0; i<cCmds; i++) {
774 if(prgCmds[i].cmdID<OLECMDID_OPEN || prgCmds[i].cmdID>OLECMDID_GETPRINTTEMPLATE) {
775 WARN("Unsupported cmdID = %d\n", prgCmds[i].cmdID);
776 prgCmds[i].cmdf = 0;
777 hres = OLECMDERR_E_NOTSUPPORTED;
778 }else {
779 if(prgCmds[i].cmdID == OLECMDID_OPEN || prgCmds[i].cmdID == OLECMDID_NEW) {
780 IOleCommandTarget *cmdtrg = NULL;
781 OLECMD olecmd;
783 prgCmds[i].cmdf = OLECMDF_SUPPORTED;
784 if(This->client) {
785 hr = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget,
786 (void**)&cmdtrg);
787 if(SUCCEEDED(hr)) {
788 olecmd.cmdID = prgCmds[i].cmdID;
789 olecmd.cmdf = 0;
791 hr = IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &olecmd, NULL);
792 if(SUCCEEDED(hr) && olecmd.cmdf)
793 prgCmds[i].cmdf = olecmd.cmdf;
795 }else {
796 ERR("This->client == NULL, native would crash\n");
798 }else {
799 prgCmds[i].cmdf = exec_table[prgCmds[i].cmdID].cmdf;
800 TRACE("cmdID = %d returning %x\n", prgCmds[i].cmdID, prgCmds[i].cmdf);
802 hres = S_OK;
806 if(pCmdText)
807 FIXME("Set pCmdText\n");
808 }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
809 ULONG i;
811 for(i=0; i<cCmds; i++) {
812 HRESULT hres = query_from_table(This, base_cmds, prgCmds+i);
813 if(hres == OLECMDERR_E_NOTSUPPORTED)
814 hres = query_from_table(This, editmode_cmds, prgCmds+i);
815 if(hres == OLECMDERR_E_NOTSUPPORTED)
816 FIXME("CGID_MSHTML: unsupported cmdID %d\n", prgCmds[i].cmdID);
819 hres = prgCmds[i-1].cmdf ? S_OK : OLECMDERR_E_NOTSUPPORTED;
821 if(pCmdText)
822 FIXME("Set pCmdText\n");
823 }else {
824 FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
825 hres = OLECMDERR_E_UNKNOWNGROUP;
828 return hres;
831 static HRESULT exec_from_table(HTMLDocument *This, const cmdtable_t *cmdtable, DWORD cmdid,
832 DWORD cmdexecopt, VARIANT *in, VARIANT *out)
834 const cmdtable_t *iter = cmdtable;
836 while(iter->id && iter->id != cmdid)
837 iter++;
839 if(!iter->id || !iter->exec)
840 return OLECMDERR_E_NOTSUPPORTED;
842 return iter->exec(This, cmdexecopt, in, out);
845 static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
846 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
848 HTMLDocument *This = CMDTARGET_THIS(iface);
850 if(!pguidCmdGroup) {
851 if(nCmdID<OLECMDID_OPEN || nCmdID>OLECMDID_GETPRINTTEMPLATE || !exec_table[nCmdID].func) {
852 WARN("Unsupported cmdID = %d\n", nCmdID);
853 return OLECMDERR_E_NOTSUPPORTED;
856 return exec_table[nCmdID].func(This, nCmdexecopt, pvaIn, pvaOut);
857 }else if(IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) {
858 FIXME("unsupported nCmdID %d of CGID_Explorer group\n", nCmdID);
859 TRACE("%p %p\n", pvaIn, pvaOut);
860 return OLECMDERR_E_NOTSUPPORTED;
861 }else if(IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup)) {
862 FIXME("unsupported nCmdID %d of CGID_ShellDocView group\n", nCmdID);
863 return OLECMDERR_E_NOTSUPPORTED;
864 }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
865 HRESULT hres = exec_from_table(This, base_cmds, nCmdID, nCmdexecopt, pvaIn, pvaOut);
866 if(hres == OLECMDERR_E_NOTSUPPORTED)
867 hres = exec_from_table(This, editmode_cmds, nCmdID,
868 nCmdexecopt, pvaIn, pvaOut);
869 if(hres == OLECMDERR_E_NOTSUPPORTED)
870 FIXME("unsupported nCmdID %d of CGID_MSHTML group\n", nCmdID);
872 return hres;
875 FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
876 return OLECMDERR_E_UNKNOWNGROUP;
879 #undef CMDTARGET_THIS
881 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
882 OleCommandTarget_QueryInterface,
883 OleCommandTarget_AddRef,
884 OleCommandTarget_Release,
885 OleCommandTarget_QueryStatus,
886 OleCommandTarget_Exec
889 void show_context_menu(HTMLDocument *This, DWORD dwID, POINT *ppt)
891 HMENU menu_res, menu;
892 DWORD cmdid;
893 HRESULT hres;
895 hres = IDocHostUIHandler_ShowContextMenu(This->hostui, dwID, ppt,
896 (IUnknown*)CMDTARGET(This), (IDispatch*)HTMLDOC(This));
897 if(hres == S_OK)
898 return;
900 menu_res = LoadMenuW(get_shdoclc(), MAKEINTRESOURCEW(IDR_BROWSE_CONTEXT_MENU));
901 menu = GetSubMenu(menu_res, dwID);
903 cmdid = TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
904 ppt->x, ppt->y, 0, This->hwnd, NULL);
905 DestroyMenu(menu_res);
907 if(cmdid)
908 IOleCommandTarget_Exec(CMDTARGET(This), &CGID_MSHTML, cmdid, 0, NULL, NULL);
911 void HTMLDocument_OleCmd_Init(HTMLDocument *This)
913 This->lpOleCommandTargetVtbl = &OleCommandTargetVtbl;