include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / mshtml / olecmd.c
blob650c44c9d2ba1835820dd5bdf4c2a89b66b6beb7
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 <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
27 #include "shlguid.h"
28 #include "mshtmdid.h"
29 #include "idispids.h"
30 #include "mshtmcid.h"
32 #include "wine/debug.h"
34 #include "mshtml_private.h"
35 #include "binding.h"
36 #include "resource.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
40 #define NSCMD_COPY "cmd_copy"
41 #define NSCMD_SELECTALL "cmd_selectAll"
43 void do_ns_command(HTMLDocumentNode *doc, const char *cmd, nsICommandParams *nsparam)
45 nsICommandManager *cmdmgr;
46 nsresult nsres;
48 TRACE("(%p)\n", doc);
50 if(!doc->browser || !doc->window)
51 return;
53 nsres = get_nsinterface((nsISupports*)doc->browser->webbrowser, &IID_nsICommandManager, (void**)&cmdmgr);
54 if(NS_FAILED(nsres)) {
55 ERR("Could not get nsICommandManager: %08lx\n", nsres);
56 return;
59 nsres = nsICommandManager_DoCommand(cmdmgr, cmd, nsparam, doc->window->base.outer_window->window_proxy);
60 if(NS_FAILED(nsres))
61 ERR("DoCommand(%s) failed: %08lx\n", debugstr_a(cmd), nsres);
63 nsICommandManager_Release(cmdmgr);
66 static nsIClipboardCommands *get_clipboard_commands(HTMLDocumentNode *doc)
68 nsIClipboardCommands *clipboard_commands;
69 nsIDocShell *doc_shell;
70 nsresult nsres;
72 if(!doc->window)
73 return NULL;
75 nsres = get_nsinterface((nsISupports*)doc->window->dom_window, &IID_nsIDocShell, (void**)&doc_shell);
76 if(NS_FAILED(nsres)) {
77 ERR("Could not get nsIDocShell interface\n");
78 return NULL;
81 nsres = nsIDocShell_QueryInterface(doc_shell, &IID_nsIClipboardCommands, (void**)&clipboard_commands);
82 nsIDocShell_Release(doc_shell);
83 if(NS_FAILED(nsres)) {
84 ERR("Could not get nsIClipboardCommands interface\n");
85 return NULL;
88 return clipboard_commands;
91 /**********************************************************
92 * IOleCommandTarget implementation
95 static inline HTMLDocumentNode *HTMLDocumentNode_from_IOleCommandTarget(IOleCommandTarget *iface)
97 return CONTAINING_RECORD(iface, HTMLDocumentNode, IOleCommandTarget_iface);
100 static inline HTMLDocumentObj *HTMLDocumentObj_from_IOleCommandTarget(IOleCommandTarget *iface)
102 return CONTAINING_RECORD(iface, HTMLDocumentObj, IOleCommandTarget_iface);
105 static HRESULT exec_open(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
107 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
108 return E_NOTIMPL;
111 static HRESULT exec_new(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
113 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
114 return E_NOTIMPL;
117 static HRESULT exec_save(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
119 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
120 return E_NOTIMPL;
123 static HRESULT exec_save_as(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
125 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
126 return E_NOTIMPL;
129 static HRESULT exec_save_copy_as(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
131 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
132 return E_NOTIMPL;
135 static nsresult set_head_text(nsIPrintSettings *settings, LPCWSTR template, BOOL head, int pos)
137 if(head) {
138 switch(pos) {
139 case 0:
140 return nsIPrintSettings_SetHeaderStrLeft(settings, template);
141 case 1:
142 return nsIPrintSettings_SetHeaderStrRight(settings, template);
143 case 2:
144 return nsIPrintSettings_SetHeaderStrCenter(settings, template);
146 }else {
147 switch(pos) {
148 case 0:
149 return nsIPrintSettings_SetFooterStrLeft(settings, template);
150 case 1:
151 return nsIPrintSettings_SetFooterStrRight(settings, template);
152 case 2:
153 return nsIPrintSettings_SetFooterStrCenter(settings, template);
157 return NS_OK;
160 static void set_print_template(nsIPrintSettings *settings, LPCWSTR template, BOOL head)
162 PRUnichar nstemplate[200]; /* FIXME: Use dynamic allocation */
163 PRUnichar *p = nstemplate;
164 LPCWSTR ptr=template;
165 int pos=0;
167 while(*ptr) {
168 if(*ptr != '&') {
169 *p++ = *ptr++;
170 continue;
173 switch(*++ptr) {
174 case '&':
175 *p++ = '&';
176 *p++ = '&';
177 ptr++;
178 break;
179 case 'b': /* change align */
180 ptr++;
181 *p = 0;
182 set_head_text(settings, nstemplate, head, pos);
183 p = nstemplate;
184 pos++;
185 break;
186 case 'd': { /* short date */
187 SYSTEMTIME systime;
188 GetLocalTime(&systime);
189 GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &systime, NULL, p,
190 sizeof(nstemplate)-(p-nstemplate)*sizeof(WCHAR));
191 p += lstrlenW(p);
192 ptr++;
193 break;
195 case 'p': /* page number */
196 *p++ = '&';
197 *p++ = 'P';
198 ptr++;
199 break;
200 case 'P': /* page count */
201 *p++ = '?'; /* FIXME */
202 ptr++;
203 break;
204 case 'u':
205 *p++ = '&';
206 *p++ = 'U';
207 ptr++;
208 break;
209 case 'w':
210 /* FIXME: set window title */
211 ptr++;
212 break;
213 default:
214 *p++ = '&';
215 *p++ = *ptr++;
219 *p = 0;
220 set_head_text(settings, nstemplate, head, pos);
222 while(++pos < 3)
223 set_head_text(settings, p, head, pos);
226 static void set_default_templates(nsIPrintSettings *settings)
228 WCHAR buf[64];
230 nsIPrintSettings_SetHeaderStrLeft(settings, L"");
231 nsIPrintSettings_SetHeaderStrRight(settings, L"");
232 nsIPrintSettings_SetHeaderStrCenter(settings, L"");
233 nsIPrintSettings_SetFooterStrLeft(settings, L"");
234 nsIPrintSettings_SetFooterStrRight(settings, L"");
235 nsIPrintSettings_SetFooterStrCenter(settings, L"");
237 if(LoadStringW(get_shdoclc(), IDS_PRINT_HEADER_TEMPLATE, buf, ARRAY_SIZE(buf)))
238 set_print_template(settings, buf, TRUE);
240 if(LoadStringW(get_shdoclc(), IDS_PRINT_FOOTER_TEMPLATE, buf, ARRAY_SIZE(buf)))
241 set_print_template(settings, buf, FALSE);
245 static HRESULT exec_print(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
247 nsIWebBrowserPrint *nsprint;
248 nsIPrintSettings *settings;
249 nsresult nsres;
251 TRACE("(%p)->(%ld %s %p)\n", doc, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
253 if(pvaOut)
254 FIXME("unsupported pvaOut\n");
256 nsres = get_nsinterface((nsISupports*)doc->browser->webbrowser, &IID_nsIWebBrowserPrint,
257 (void**)&nsprint);
258 if(NS_FAILED(nsres)) {
259 ERR("Could not get nsIWebBrowserPrint: %08lx\n", nsres);
260 return S_OK;
263 nsres = nsIWebBrowserPrint_GetGlobalPrintSettings(nsprint, &settings);
264 if(NS_FAILED(nsres))
265 ERR("GetCurrentPrintSettings failed: %08lx\n", nsres);
267 set_default_templates(settings);
269 if(pvaIn) {
270 switch(V_VT(pvaIn)) {
271 case VT_BYREF|VT_ARRAY: {
272 VARIANT *opts;
273 DWORD opts_cnt;
275 if(V_ARRAY(pvaIn)->cDims != 1)
276 WARN("cDims = %d\n", V_ARRAY(pvaIn)->cDims);
278 SafeArrayAccessData(V_ARRAY(pvaIn), (void**)&opts);
279 opts_cnt = V_ARRAY(pvaIn)->rgsabound[0].cElements;
281 if(opts_cnt >= 1) {
282 switch(V_VT(opts)) {
283 case VT_BSTR:
284 TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts)));
285 set_print_template(settings, V_BSTR(opts), TRUE);
286 break;
287 case VT_NULL:
288 break;
289 default:
290 WARN("opts = %s\n", debugstr_variant(opts));
294 if(opts_cnt >= 2) {
295 switch(V_VT(opts+1)) {
296 case VT_BSTR:
297 TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts+1)));
298 set_print_template(settings, V_BSTR(opts+1), FALSE);
299 break;
300 case VT_NULL:
301 break;
302 default:
303 WARN("opts[1] = %s\n", debugstr_variant(opts+1));
307 if(opts_cnt >= 3)
308 FIXME("Unsupported opts_cnt %ld\n", opts_cnt);
310 SafeArrayUnaccessData(V_ARRAY(pvaIn));
311 break;
313 default:
314 FIXME("unsupported arg %s\n", debugstr_variant(pvaIn));
318 nsres = nsIWebBrowserPrint_Print(nsprint, settings, NULL);
319 if(NS_FAILED(nsres))
320 ERR("Print failed: %08lx\n", nsres);
322 nsIWebBrowserPrint_Release(nsprint);
324 return S_OK;
327 static HRESULT exec_print_preview(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
329 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
330 return E_NOTIMPL;
333 static HRESULT exec_page_setup(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
335 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
336 return E_NOTIMPL;
339 static HRESULT exec_spell(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
341 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
342 return E_NOTIMPL;
345 static HRESULT exec_properties(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
347 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
348 return E_NOTIMPL;
351 static HRESULT exec_cut(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
353 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
354 return E_NOTIMPL;
357 static HRESULT exec_copy(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
359 TRACE("(%p)->(%ld %s %p)\n", doc, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
361 do_ns_command(doc, NSCMD_COPY, NULL);
362 return S_OK;
365 static HRESULT exec_paste(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
367 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
368 return E_NOTIMPL;
371 static HRESULT exec_paste_special(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
373 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
374 return E_NOTIMPL;
377 static HRESULT exec_undo(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
379 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
380 return E_NOTIMPL;
383 static HRESULT exec_rendo(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
385 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
386 return E_NOTIMPL;
389 static HRESULT exec_select_all(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *in, VARIANT *out)
391 TRACE("(%p)\n", doc);
393 if(in || out)
394 FIXME("unsupported args\n");
396 if(!doc->browser)
397 return E_UNEXPECTED;
399 do_ns_command(doc, NSCMD_SELECTALL, NULL);
400 update_doc(doc->browser->doc, UPDATE_UI);
401 return S_OK;
404 static HRESULT exec_clear_selection(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
406 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
407 return E_NOTIMPL;
410 static HRESULT exec_zoom(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
412 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
413 return E_NOTIMPL;
416 static HRESULT exec_get_zoom_range(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
418 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
419 return E_NOTIMPL;
422 typedef struct {
423 task_t header;
424 HTMLOuterWindow *window;
425 }refresh_task_t;
427 static void refresh_proc(task_t *_task)
429 refresh_task_t *task = (refresh_task_t*)_task;
430 HTMLOuterWindow *window = task->window;
432 TRACE("%p\n", window);
434 window->readystate = READYSTATE_UNINITIALIZED;
436 if(window->browser && window->browser->doc->client_cmdtrg) {
437 VARIANT var;
439 V_VT(&var) = VT_I4;
440 V_I4(&var) = 0;
441 IOleCommandTarget_Exec(window->browser->doc->client_cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL);
444 load_uri(window, window->uri, BINDING_REFRESH|BINDING_NOFRAG);
447 static void refresh_destr(task_t *_task)
449 refresh_task_t *task = (refresh_task_t*)_task;
451 IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface);
454 HRESULT reload_page(HTMLOuterWindow *window)
456 refresh_task_t *task;
458 task = malloc(sizeof(*task));
459 if(!task)
460 return E_OUTOFMEMORY;
462 IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
463 task->window = window;
465 return push_task(&task->header, refresh_proc, refresh_destr, window->task_magic);
468 static HRESULT exec_refresh(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
470 HTMLDocumentObj *doc_obj;
471 HRESULT hres;
473 TRACE("(%p)->(%ld %s %p)\n", doc, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
475 if(doc != doc->browser->doc->doc_node) {
476 FIXME("Unsupported on frame documents\n");
477 return E_NOTIMPL;
479 doc_obj = doc->browser->doc;
481 if(doc_obj->client) {
482 IOleCommandTarget *olecmd;
484 hres = IOleClientSite_QueryInterface(doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd);
485 if(SUCCEEDED(hres)) {
486 hres = IOleCommandTarget_Exec(olecmd, &CGID_DocHostCommandHandler, 2300, nCmdexecopt, pvaIn, pvaOut);
487 IOleCommandTarget_Release(olecmd);
488 if(SUCCEEDED(hres))
489 return S_OK;
493 if(!doc->window || !doc->window->base.outer_window)
494 return E_UNEXPECTED;
496 return reload_page(doc->window->base.outer_window);
499 static HRESULT exec_stop(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
501 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
502 return E_NOTIMPL;
505 static HRESULT exec_stop_download(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
507 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
508 return E_NOTIMPL;
511 static HRESULT exec_find(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
513 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
514 return E_NOTIMPL;
517 static HRESULT exec_delete(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
519 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
520 return E_NOTIMPL;
523 static HRESULT exec_enable_interaction(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
525 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
526 return E_NOTIMPL;
529 static HRESULT exec_on_unload(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
531 TRACE("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
533 /* Tests show that we have nothing more to do here */
535 if(pvaOut) {
536 V_VT(pvaOut) = VT_BOOL;
537 V_BOOL(pvaOut) = VARIANT_TRUE;
540 return S_OK;
543 static HRESULT exec_show_page_setup(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
545 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
546 return E_NOTIMPL;
549 static HRESULT exec_show_print(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
551 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
552 return E_NOTIMPL;
555 static HRESULT exec_close(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
557 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
558 return E_NOTIMPL;
561 static HRESULT exec_set_print_template(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
563 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
564 return E_NOTIMPL;
567 static HRESULT exec_get_print_template(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
569 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
570 return E_NOTIMPL;
573 static HRESULT exec_optical_zoom(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
575 TRACE("(%p)->(%ld %s %p)\n", doc, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
577 if(pvaIn && V_VT(pvaIn) != VT_I4) {
578 FIXME("Unsupported argument %s\n", debugstr_variant(pvaIn));
579 return E_NOTIMPL;
582 if(pvaIn)
583 set_viewer_zoom(doc->browser, (float)V_I4(pvaIn)/100);
584 if(pvaOut) {
585 V_VT(pvaOut) = VT_I4;
586 V_I4(pvaOut) = get_viewer_zoom(doc->browser) * 100;
588 return S_OK;
591 static HRESULT query_mshtml_copy(HTMLDocumentNode *doc, OLECMD *cmd)
593 FIXME("(%p)\n", doc);
594 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
595 return S_OK;
598 static HRESULT exec_mshtml_copy(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
600 TRACE("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
602 if(doc->browser->usermode == EDITMODE)
603 return editor_exec_copy(doc, cmdexecopt, in, out);
605 do_ns_command(doc, NSCMD_COPY, NULL);
606 return S_OK;
609 static HRESULT query_mshtml_cut(HTMLDocumentNode *doc, OLECMD *cmd)
611 FIXME("(%p)\n", doc);
612 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
613 return S_OK;
616 static HRESULT exec_mshtml_cut(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
618 nsIClipboardCommands *clipboard_commands;
619 nsresult nsres;
621 TRACE("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
623 if(doc->browser->usermode == EDITMODE)
624 return editor_exec_cut(doc, cmdexecopt, in, out);
626 clipboard_commands = get_clipboard_commands(doc);
627 if(!clipboard_commands)
628 return E_UNEXPECTED;
630 nsres = nsIClipboardCommands_CutSelection(clipboard_commands);
631 nsIClipboardCommands_Release(clipboard_commands);
632 if(NS_FAILED(nsres)) {
633 ERR("Paste failed: %08lx\n", nsres);
634 return E_FAIL;
637 return S_OK;
640 static HRESULT query_mshtml_paste(HTMLDocumentNode *doc, OLECMD *cmd)
642 FIXME("(%p)\n", doc);
643 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
644 return S_OK;
647 static HRESULT exec_mshtml_paste(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
649 nsIClipboardCommands *clipboard_commands;
650 nsresult nsres;
652 TRACE("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
654 if(doc->browser->usermode == EDITMODE)
655 return editor_exec_paste(doc, cmdexecopt, in, out);
657 clipboard_commands = get_clipboard_commands(doc);
658 if(!clipboard_commands)
659 return E_UNEXPECTED;
661 nsres = nsIClipboardCommands_Paste(clipboard_commands);
662 nsIClipboardCommands_Release(clipboard_commands);
663 if(NS_FAILED(nsres)) {
664 ERR("Paste failed: %08lx\n", nsres);
665 return E_FAIL;
668 return S_OK;
671 static HRESULT query_selall_status(HTMLDocumentNode *doc, OLECMD *cmd)
673 TRACE("(%p)->(%p)\n", doc, cmd);
675 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
676 return S_OK;
679 static HRESULT exec_browsemode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
681 WARN("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
683 if(in || out)
684 FIXME("unsupported args\n");
686 doc->browser->usermode = BROWSEMODE;
688 return S_OK;
691 static HRESULT exec_editmode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
693 HTMLDocumentObj *doc_obj;
694 HRESULT hres;
696 TRACE("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
698 if(in || out)
699 FIXME("unsupported args\n");
701 doc_obj = doc->browser->doc;
702 IUnknown_AddRef(doc_obj->outer_unk);
703 hres = setup_edit_mode(doc_obj);
704 IUnknown_Release(doc_obj->outer_unk);
705 return hres;
708 static HRESULT exec_htmleditmode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
710 FIXME("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
711 return S_OK;
714 static HRESULT exec_baselinefont3(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
716 FIXME("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
717 return S_OK;
720 static HRESULT exec_respectvisibility_indesign(HTMLDocumentNode *doc, DWORD cmdexecopt,
721 VARIANT *in, VARIANT *out)
723 TRACE("(%p)->(%lx %s %p)\n", doc, cmdexecopt, debugstr_variant(in), out);
725 /* This is turned on by default in Gecko. */
726 if(!in || V_VT(in) != VT_BOOL || !V_BOOL(in))
727 FIXME("Unsupported argument %s\n", debugstr_variant(in));
729 return S_OK;
732 static HRESULT query_enabled_stub(HTMLDocumentNode *doc, OLECMD *cmd)
734 switch(cmd->cmdID) {
735 case IDM_PRINT:
736 FIXME("CGID_MSHTML: IDM_PRINT\n");
737 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
738 break;
739 case IDM_BLOCKDIRLTR:
740 FIXME("CGID_MSHTML: IDM_BLOCKDIRLTR\n");
741 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
742 break;
743 case IDM_BLOCKDIRRTL:
744 FIXME("CGID_MSHTML: IDM_BLOCKDIRRTL\n");
745 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
746 break;
749 return S_OK;
752 static const struct {
753 OLECMDF cmdf;
754 HRESULT (*func)(HTMLDocumentNode*,DWORD,VARIANT*,VARIANT*);
755 } exec_table[] = {
756 {0},
757 { OLECMDF_SUPPORTED, exec_open }, /* OLECMDID_OPEN */
758 { OLECMDF_SUPPORTED, exec_new }, /* OLECMDID_NEW */
759 { OLECMDF_SUPPORTED, exec_save }, /* OLECMDID_SAVE */
760 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_save_as }, /* OLECMDID_SAVEAS */
761 { OLECMDF_SUPPORTED, exec_save_copy_as }, /* OLECMDID_SAVECOPYAS */
762 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_print }, /* OLECMDID_PRINT */
763 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_print_preview }, /* OLECMDID_PRINTPREVIEW */
764 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_page_setup }, /* OLECMDID_PAGESETUP */
765 { OLECMDF_SUPPORTED, exec_spell }, /* OLECMDID_SPELL */
766 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_properties }, /* OLECMDID_PROPERTIES */
767 { OLECMDF_SUPPORTED, exec_cut }, /* OLECMDID_CUT */
768 { OLECMDF_SUPPORTED, exec_copy }, /* OLECMDID_COPY */
769 { OLECMDF_SUPPORTED, exec_paste }, /* OLECMDID_PASTE */
770 { OLECMDF_SUPPORTED, exec_paste_special }, /* OLECMDID_PASTESPECIAL */
771 { OLECMDF_SUPPORTED, exec_undo }, /* OLECMDID_UNDO */
772 { OLECMDF_SUPPORTED, exec_rendo }, /* OLECMDID_REDO */
773 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_select_all }, /* OLECMDID_SELECTALL */
774 { OLECMDF_SUPPORTED, exec_clear_selection }, /* OLECMDID_CLEARSELECTION */
775 { OLECMDF_SUPPORTED, exec_zoom }, /* OLECMDID_ZOOM */
776 { OLECMDF_SUPPORTED, exec_get_zoom_range }, /* OLECMDID_GETZOOMRANGE */
777 {0},
778 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_refresh }, /* OLECMDID_REFRESH */
779 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_stop }, /* OLECMDID_STOP */
780 {0},{0},{0},{0},{0},{0},
781 { OLECMDF_SUPPORTED, exec_stop_download }, /* OLECMDID_STOPDOWNLOAD */
782 {0},
783 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_find }, /* OLECMDID_FIND */
784 { OLECMDF_SUPPORTED, exec_delete }, /* OLECMDID_DELETE */
785 {0},{0},
786 { OLECMDF_SUPPORTED, exec_enable_interaction }, /* OLECMDID_ENABLE_INTERACTION */
787 { OLECMDF_SUPPORTED, exec_on_unload }, /* OLECMDID_ONUNLOAD */
788 {0},{0},{0},{0},{0},
789 { OLECMDF_SUPPORTED, exec_show_page_setup }, /* OLECMDID_SHOWPAGESETUP */
790 { OLECMDF_SUPPORTED, exec_show_print }, /* OLECMDID_SHOWPRINT */
791 {0},{0},
792 { OLECMDF_SUPPORTED, exec_close }, /* OLECMDID_CLOSE */
793 {0},{0},{0},
794 { OLECMDF_SUPPORTED, exec_set_print_template }, /* OLECMDID_SETPRINTTEMPLATE */
795 { OLECMDF_SUPPORTED, exec_get_print_template }, /* OLECMDID_GETPRINTTEMPLATE */
796 {0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
797 { 0, /* not reported as supported */ exec_optical_zoom } /* OLECMDID_OPTICAL_ZOOM */
800 static const cmdtable_t base_cmds[] = {
801 {IDM_COPY, query_mshtml_copy, exec_mshtml_copy},
802 {IDM_PASTE, query_mshtml_paste, exec_mshtml_paste},
803 {IDM_CUT, query_mshtml_cut, exec_mshtml_cut},
804 {IDM_SELECTALL, query_selall_status, exec_select_all},
805 {IDM_BROWSEMODE, NULL, exec_browsemode},
806 {IDM_EDITMODE, NULL, exec_editmode},
807 {IDM_PRINT, query_enabled_stub, exec_print},
808 {IDM_HTMLEDITMODE, NULL, exec_htmleditmode},
809 {IDM_BASELINEFONT3, NULL, exec_baselinefont3},
810 {IDM_BLOCKDIRLTR, query_enabled_stub, NULL},
811 {IDM_BLOCKDIRRTL, query_enabled_stub, NULL},
812 {IDM_RESPECTVISIBILITY_INDESIGN, NULL, exec_respectvisibility_indesign},
813 {0,NULL,NULL}
816 static HRESULT WINAPI DocNodeOleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
818 HTMLDocumentNode *This = HTMLDocumentNode_from_IOleCommandTarget(iface);
819 return IHTMLDOMNode_QueryInterface(&This->node.IHTMLDOMNode_iface, riid, ppv);
822 static ULONG WINAPI DocNodeOleCommandTarget_AddRef(IOleCommandTarget *iface)
824 HTMLDocumentNode *This = HTMLDocumentNode_from_IOleCommandTarget(iface);
825 return IHTMLDOMNode_AddRef(&This->node.IHTMLDOMNode_iface);
828 static ULONG WINAPI DocNodeOleCommandTarget_Release(IOleCommandTarget *iface)
830 HTMLDocumentNode *This = HTMLDocumentNode_from_IOleCommandTarget(iface);
831 return IHTMLDOMNode_Release(&This->node.IHTMLDOMNode_iface);
834 static HRESULT query_from_table(HTMLDocumentNode *doc, const cmdtable_t *cmdtable, OLECMD *cmd)
836 const cmdtable_t *iter = cmdtable;
838 cmd->cmdf = 0;
840 while(iter->id && iter->id != cmd->cmdID)
841 iter++;
843 if(!iter->id || !iter->query)
844 return OLECMDERR_E_NOTSUPPORTED;
846 return iter->query(doc, cmd);
849 static HRESULT WINAPI DocNodeOleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
850 ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
852 HTMLDocumentNode *This = HTMLDocumentNode_from_IOleCommandTarget(iface);
853 HRESULT hres;
855 TRACE("(%p)->(%s %ld %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
857 if(pCmdText)
858 FIXME("Unsupported pCmdText\n");
859 if(!This->browser)
860 return E_UNEXPECTED;
861 if(!cCmds)
862 return S_OK;
864 if(!pguidCmdGroup) {
865 ULONG i;
867 for(i=0; i<cCmds; i++) {
868 if(prgCmds[i].cmdID < OLECMDID_OPEN || prgCmds[i].cmdID >= ARRAY_SIZE(exec_table)) {
869 WARN("Unsupported cmdID = %ld\n", prgCmds[i].cmdID);
870 prgCmds[i].cmdf = 0;
871 }else {
872 if(prgCmds[i].cmdID == OLECMDID_OPEN || prgCmds[i].cmdID == OLECMDID_NEW) {
873 IOleCommandTarget *cmdtrg = NULL;
874 OLECMD olecmd;
876 prgCmds[i].cmdf = OLECMDF_SUPPORTED;
877 if(This->doc_obj->client) {
878 hres = IOleClientSite_QueryInterface(This->doc_obj->client, &IID_IOleCommandTarget,
879 (void**)&cmdtrg);
880 if(SUCCEEDED(hres)) {
881 olecmd.cmdID = prgCmds[i].cmdID;
882 olecmd.cmdf = 0;
884 hres = IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &olecmd, NULL);
885 if(SUCCEEDED(hres) && olecmd.cmdf)
886 prgCmds[i].cmdf = olecmd.cmdf;
888 }else {
889 ERR("This->client == NULL, native would crash\n");
891 }else {
892 prgCmds[i].cmdf = exec_table[prgCmds[i].cmdID].cmdf;
893 TRACE("cmdID = %ld returning %lx\n", prgCmds[i].cmdID, prgCmds[i].cmdf);
898 return (prgCmds[cCmds-1].cmdf & OLECMDF_SUPPORTED) ? S_OK : OLECMDERR_E_NOTSUPPORTED;
901 if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
902 ULONG i;
904 for(i=0; i<cCmds; i++) {
905 hres = query_from_table(This, base_cmds, prgCmds+i);
906 if(hres == OLECMDERR_E_NOTSUPPORTED)
907 hres = query_from_table(This, editmode_cmds, prgCmds+i);
908 if(hres == OLECMDERR_E_NOTSUPPORTED)
909 FIXME("CGID_MSHTML: unsupported cmdID %ld\n", prgCmds[i].cmdID);
912 return (prgCmds[cCmds-1].cmdf & OLECMDF_SUPPORTED) ? S_OK : OLECMDERR_E_NOTSUPPORTED;
915 FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
916 return OLECMDERR_E_UNKNOWNGROUP;
919 static HRESULT exec_from_table(HTMLDocumentNode *doc, const cmdtable_t *cmdtable, DWORD cmdid,
920 DWORD cmdexecopt, VARIANT *in, VARIANT *out)
922 const cmdtable_t *iter = cmdtable;
924 while(iter->id && iter->id != cmdid)
925 iter++;
927 if(!iter->id || !iter->exec)
928 return OLECMDERR_E_NOTSUPPORTED;
930 return iter->exec(doc, cmdexecopt, in, out);
933 static HRESULT WINAPI DocNodeOleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
934 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
936 HTMLDocumentNode *This = HTMLDocumentNode_from_IOleCommandTarget(iface);
938 TRACE("(%p)->(%s %ld %ld %s %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, wine_dbgstr_variant(pvaIn), pvaOut);
940 if(!This->browser)
941 return E_UNEXPECTED;
943 if(!pguidCmdGroup) {
944 if(nCmdID < OLECMDID_OPEN || nCmdID >= ARRAY_SIZE(exec_table) || !exec_table[nCmdID].func) {
945 WARN("Unsupported cmdID = %ld\n", nCmdID);
946 return OLECMDERR_E_NOTSUPPORTED;
949 return exec_table[nCmdID].func(This, nCmdexecopt, pvaIn, pvaOut);
950 }else if(IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) {
951 FIXME("unsupported nCmdID %ld of CGID_Explorer group\n", nCmdID);
952 TRACE("%p %p\n", pvaIn, pvaOut);
953 return OLECMDERR_E_NOTSUPPORTED;
954 }else if(IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup)) {
955 FIXME("unsupported nCmdID %ld of CGID_ShellDocView group\n", nCmdID);
956 return OLECMDERR_E_NOTSUPPORTED;
957 }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
958 HRESULT hres = exec_from_table(This, base_cmds, nCmdID, nCmdexecopt, pvaIn, pvaOut);
959 if(hres == OLECMDERR_E_NOTSUPPORTED)
960 hres = exec_from_table(This, editmode_cmds, nCmdID,
961 nCmdexecopt, pvaIn, pvaOut);
962 if(hres == OLECMDERR_E_NOTSUPPORTED)
963 FIXME("unsupported nCmdID %ld of CGID_MSHTML group\n", nCmdID);
965 return hres;
968 FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
969 return OLECMDERR_E_UNKNOWNGROUP;
972 static const IOleCommandTargetVtbl DocNodeOleCommandTargetVtbl = {
973 DocNodeOleCommandTarget_QueryInterface,
974 DocNodeOleCommandTarget_AddRef,
975 DocNodeOleCommandTarget_Release,
976 DocNodeOleCommandTarget_QueryStatus,
977 DocNodeOleCommandTarget_Exec
980 static HRESULT WINAPI DocObjOleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
982 HTMLDocumentObj *This = HTMLDocumentObj_from_IOleCommandTarget(iface);
983 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
986 static ULONG WINAPI DocObjOleCommandTarget_AddRef(IOleCommandTarget *iface)
988 HTMLDocumentObj *This = HTMLDocumentObj_from_IOleCommandTarget(iface);
989 return IUnknown_AddRef(This->outer_unk);
992 static ULONG WINAPI DocObjOleCommandTarget_Release(IOleCommandTarget *iface)
994 HTMLDocumentObj *This = HTMLDocumentObj_from_IOleCommandTarget(iface);
995 return IUnknown_Release(This->outer_unk);
998 static HRESULT WINAPI DocObjOleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
999 ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
1001 HTMLDocumentObj *This = HTMLDocumentObj_from_IOleCommandTarget(iface);
1003 return IOleCommandTarget_QueryStatus(&This->doc_node->IOleCommandTarget_iface,
1004 pguidCmdGroup, cCmds, prgCmds, pCmdText);
1007 static HRESULT WINAPI DocObjOleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1008 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1010 HTMLDocumentObj *This = HTMLDocumentObj_from_IOleCommandTarget(iface);
1012 return IOleCommandTarget_Exec(&This->doc_node->IOleCommandTarget_iface,
1013 pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
1016 static const IOleCommandTargetVtbl DocObjOleCommandTargetVtbl = {
1017 DocObjOleCommandTarget_QueryInterface,
1018 DocObjOleCommandTarget_AddRef,
1019 DocObjOleCommandTarget_Release,
1020 DocObjOleCommandTarget_QueryStatus,
1021 DocObjOleCommandTarget_Exec
1024 void show_context_menu(HTMLDocumentObj *This, DWORD dwID, POINT *ppt, IDispatch *elem)
1026 HMENU menu_res, menu;
1027 DWORD cmdid;
1029 if(This->hostui && S_OK == IDocHostUIHandler_ShowContextMenu(This->hostui,
1030 dwID, ppt, (IUnknown*)&This->IOleCommandTarget_iface, elem))
1031 return;
1033 menu_res = LoadMenuW(get_shdoclc(), MAKEINTRESOURCEW(IDR_BROWSE_CONTEXT_MENU));
1034 menu = GetSubMenu(menu_res, dwID);
1036 cmdid = TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
1037 ppt->x, ppt->y, 0, This->hwnd, NULL);
1038 DestroyMenu(menu_res);
1040 if(cmdid)
1041 IOleCommandTarget_Exec(&This->IOleCommandTarget_iface, &CGID_MSHTML, cmdid, 0,
1042 NULL, NULL);
1045 void HTMLDocumentNode_OleCmd_Init(HTMLDocumentNode *This)
1047 This->IOleCommandTarget_iface.lpVtbl = &DocNodeOleCommandTargetVtbl;
1050 void HTMLDocumentObj_OleCmd_Init(HTMLDocumentObj *This)
1052 This->IOleCommandTarget_iface.lpVtbl = &DocObjOleCommandTargetVtbl;