mshtml: Add separate task list for tasks dispatching events.
[wine.git] / dlls / mshtml / olecmd.c
blob9e59778ccb98eb90278819abbdd69ce70b06998f
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 nsres = get_nsinterface((nsISupports*)doc->outer_window->nswindow, &IID_nsIDocShell, (void**)&doc_shell);
73 if(NS_FAILED(nsres)) {
74 ERR("Could not get nsIDocShell interface\n");
75 return NULL;
78 nsres = nsIDocShell_QueryInterface(doc_shell, &IID_nsIClipboardCommands, (void**)&clipboard_commands);
79 nsIDocShell_Release(doc_shell);
80 if(NS_FAILED(nsres)) {
81 ERR("Could not get nsIClipboardCommands interface\n");
82 return NULL;
85 return clipboard_commands;
88 /**********************************************************
89 * IOleCommandTarget implementation
92 static inline HTMLDocumentNode *HTMLDocumentNode_from_IOleCommandTarget(IOleCommandTarget *iface)
94 return CONTAINING_RECORD(iface, HTMLDocumentNode, IOleCommandTarget_iface);
97 static inline HTMLDocumentObj *HTMLDocumentObj_from_IOleCommandTarget(IOleCommandTarget *iface)
99 return CONTAINING_RECORD(iface, HTMLDocumentObj, IOleCommandTarget_iface);
102 static HRESULT exec_open(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
104 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
105 return E_NOTIMPL;
108 static HRESULT exec_new(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
110 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
111 return E_NOTIMPL;
114 static HRESULT exec_save(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
116 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
117 return E_NOTIMPL;
120 static HRESULT exec_save_as(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
122 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
123 return E_NOTIMPL;
126 static HRESULT exec_save_copy_as(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
128 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
129 return E_NOTIMPL;
132 static nsresult set_head_text(nsIPrintSettings *settings, LPCWSTR template, BOOL head, int pos)
134 if(head) {
135 switch(pos) {
136 case 0:
137 return nsIPrintSettings_SetHeaderStrLeft(settings, template);
138 case 1:
139 return nsIPrintSettings_SetHeaderStrRight(settings, template);
140 case 2:
141 return nsIPrintSettings_SetHeaderStrCenter(settings, template);
143 }else {
144 switch(pos) {
145 case 0:
146 return nsIPrintSettings_SetFooterStrLeft(settings, template);
147 case 1:
148 return nsIPrintSettings_SetFooterStrRight(settings, template);
149 case 2:
150 return nsIPrintSettings_SetFooterStrCenter(settings, template);
154 return NS_OK;
157 static void set_print_template(nsIPrintSettings *settings, LPCWSTR template, BOOL head)
159 PRUnichar nstemplate[200]; /* FIXME: Use dynamic allocation */
160 PRUnichar *p = nstemplate;
161 LPCWSTR ptr=template;
162 int pos=0;
164 while(*ptr) {
165 if(*ptr != '&') {
166 *p++ = *ptr++;
167 continue;
170 switch(*++ptr) {
171 case '&':
172 *p++ = '&';
173 *p++ = '&';
174 ptr++;
175 break;
176 case 'b': /* change align */
177 ptr++;
178 *p = 0;
179 set_head_text(settings, nstemplate, head, pos);
180 p = nstemplate;
181 pos++;
182 break;
183 case 'd': { /* short date */
184 SYSTEMTIME systime;
185 GetLocalTime(&systime);
186 GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &systime, NULL, p,
187 sizeof(nstemplate)-(p-nstemplate)*sizeof(WCHAR));
188 p += lstrlenW(p);
189 ptr++;
190 break;
192 case 'p': /* page number */
193 *p++ = '&';
194 *p++ = 'P';
195 ptr++;
196 break;
197 case 'P': /* page count */
198 *p++ = '?'; /* FIXME */
199 ptr++;
200 break;
201 case 'u':
202 *p++ = '&';
203 *p++ = 'U';
204 ptr++;
205 break;
206 case 'w':
207 /* FIXME: set window title */
208 ptr++;
209 break;
210 default:
211 *p++ = '&';
212 *p++ = *ptr++;
216 *p = 0;
217 set_head_text(settings, nstemplate, head, pos);
219 while(++pos < 3)
220 set_head_text(settings, p, head, pos);
223 static void set_default_templates(nsIPrintSettings *settings)
225 WCHAR buf[64];
227 nsIPrintSettings_SetHeaderStrLeft(settings, L"");
228 nsIPrintSettings_SetHeaderStrRight(settings, L"");
229 nsIPrintSettings_SetHeaderStrCenter(settings, L"");
230 nsIPrintSettings_SetFooterStrLeft(settings, L"");
231 nsIPrintSettings_SetFooterStrRight(settings, L"");
232 nsIPrintSettings_SetFooterStrCenter(settings, L"");
234 if(LoadStringW(get_shdoclc(), IDS_PRINT_HEADER_TEMPLATE, buf, ARRAY_SIZE(buf)))
235 set_print_template(settings, buf, TRUE);
237 if(LoadStringW(get_shdoclc(), IDS_PRINT_FOOTER_TEMPLATE, buf, ARRAY_SIZE(buf)))
238 set_print_template(settings, buf, FALSE);
242 static HRESULT exec_print(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
244 nsIWebBrowserPrint *nsprint;
245 nsIPrintSettings *settings;
246 nsresult nsres;
248 TRACE("(%p)->(%ld %s %p)\n", doc, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
250 if(pvaOut)
251 FIXME("unsupported pvaOut\n");
253 nsres = get_nsinterface((nsISupports*)doc->browser->webbrowser, &IID_nsIWebBrowserPrint,
254 (void**)&nsprint);
255 if(NS_FAILED(nsres)) {
256 ERR("Could not get nsIWebBrowserPrint: %08lx\n", nsres);
257 return S_OK;
260 nsres = nsIWebBrowserPrint_GetGlobalPrintSettings(nsprint, &settings);
261 if(NS_FAILED(nsres))
262 ERR("GetCurrentPrintSettings failed: %08lx\n", nsres);
264 set_default_templates(settings);
266 if(pvaIn) {
267 switch(V_VT(pvaIn)) {
268 case VT_BYREF|VT_ARRAY: {
269 VARIANT *opts;
270 DWORD opts_cnt;
272 if(V_ARRAY(pvaIn)->cDims != 1)
273 WARN("cDims = %d\n", V_ARRAY(pvaIn)->cDims);
275 SafeArrayAccessData(V_ARRAY(pvaIn), (void**)&opts);
276 opts_cnt = V_ARRAY(pvaIn)->rgsabound[0].cElements;
278 if(opts_cnt >= 1) {
279 switch(V_VT(opts)) {
280 case VT_BSTR:
281 TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts)));
282 set_print_template(settings, V_BSTR(opts), TRUE);
283 break;
284 case VT_NULL:
285 break;
286 default:
287 WARN("opts = %s\n", debugstr_variant(opts));
291 if(opts_cnt >= 2) {
292 switch(V_VT(opts+1)) {
293 case VT_BSTR:
294 TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts+1)));
295 set_print_template(settings, V_BSTR(opts+1), FALSE);
296 break;
297 case VT_NULL:
298 break;
299 default:
300 WARN("opts[1] = %s\n", debugstr_variant(opts+1));
304 if(opts_cnt >= 3)
305 FIXME("Unsupported opts_cnt %ld\n", opts_cnt);
307 SafeArrayUnaccessData(V_ARRAY(pvaIn));
308 break;
310 default:
311 FIXME("unsupported arg %s\n", debugstr_variant(pvaIn));
315 nsres = nsIWebBrowserPrint_Print(nsprint, settings, NULL);
316 if(NS_FAILED(nsres))
317 ERR("Print failed: %08lx\n", nsres);
319 nsIWebBrowserPrint_Release(nsprint);
321 return S_OK;
324 static HRESULT exec_print_preview(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
326 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
327 return E_NOTIMPL;
330 static HRESULT exec_page_setup(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
332 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
333 return E_NOTIMPL;
336 static HRESULT exec_spell(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
338 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
339 return E_NOTIMPL;
342 static HRESULT exec_properties(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
344 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
345 return E_NOTIMPL;
348 static HRESULT exec_cut(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
350 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
351 return E_NOTIMPL;
354 static HRESULT exec_copy(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
356 TRACE("(%p)->(%ld %s %p)\n", doc, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
358 do_ns_command(doc, NSCMD_COPY, NULL);
359 return S_OK;
362 static HRESULT exec_paste(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
364 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
365 return E_NOTIMPL;
368 static HRESULT exec_paste_special(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
370 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
371 return E_NOTIMPL;
374 static HRESULT exec_undo(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
376 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
377 return E_NOTIMPL;
380 static HRESULT exec_rendo(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
382 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
383 return E_NOTIMPL;
386 static HRESULT exec_select_all(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *in, VARIANT *out)
388 TRACE("(%p)\n", doc);
390 if(in || out)
391 FIXME("unsupported args\n");
393 if(!doc->browser)
394 return E_UNEXPECTED;
396 do_ns_command(doc, NSCMD_SELECTALL, NULL);
397 update_doc(doc->browser->doc, UPDATE_UI);
398 return S_OK;
401 static HRESULT exec_clear_selection(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
403 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
404 return E_NOTIMPL;
407 static HRESULT exec_zoom(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
409 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
410 return E_NOTIMPL;
413 static HRESULT exec_get_zoom_range(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
415 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
416 return E_NOTIMPL;
419 typedef struct {
420 task_t header;
421 HTMLOuterWindow *window;
422 }refresh_task_t;
424 static void refresh_proc(task_t *_task)
426 refresh_task_t *task = (refresh_task_t*)_task;
427 HTMLOuterWindow *window = task->window;
429 TRACE("%p\n", window);
431 window->readystate = READYSTATE_UNINITIALIZED;
433 if(window->browser && window->browser->doc->client_cmdtrg) {
434 VARIANT var;
436 V_VT(&var) = VT_I4;
437 V_I4(&var) = 0;
438 IOleCommandTarget_Exec(window->browser->doc->client_cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL);
441 load_uri(task->window, task->window->uri, BINDING_REFRESH|BINDING_NOFRAG);
444 static void refresh_destr(task_t *_task)
446 refresh_task_t *task = (refresh_task_t*)_task;
448 IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface);
451 HRESULT reload_page(HTMLOuterWindow *window)
453 refresh_task_t *task;
455 task = malloc(sizeof(*task));
456 if(!task)
457 return E_OUTOFMEMORY;
459 IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
460 task->window = window;
462 return push_task(&task->header, refresh_proc, refresh_destr, window->task_magic);
465 static HRESULT exec_refresh(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
467 HTMLDocumentObj *doc_obj;
468 HRESULT hres;
470 TRACE("(%p)->(%ld %s %p)\n", doc, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
472 if(doc != doc->browser->doc->doc_node) {
473 FIXME("Unsupported on frame documents\n");
474 return E_NOTIMPL;
476 doc_obj = doc->browser->doc;
478 if(doc_obj->client) {
479 IOleCommandTarget *olecmd;
481 hres = IOleClientSite_QueryInterface(doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd);
482 if(SUCCEEDED(hres)) {
483 hres = IOleCommandTarget_Exec(olecmd, &CGID_DocHostCommandHandler, 2300, nCmdexecopt, pvaIn, pvaOut);
484 IOleCommandTarget_Release(olecmd);
485 if(SUCCEEDED(hres))
486 return S_OK;
490 if(!doc->outer_window)
491 return E_UNEXPECTED;
493 return reload_page(doc->outer_window);
496 static HRESULT exec_stop(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
498 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
499 return E_NOTIMPL;
502 static HRESULT exec_stop_download(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
504 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
505 return E_NOTIMPL;
508 static HRESULT exec_find(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
510 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
511 return E_NOTIMPL;
514 static HRESULT exec_delete(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
516 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
517 return E_NOTIMPL;
520 static HRESULT exec_enable_interaction(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
522 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
523 return E_NOTIMPL;
526 static HRESULT exec_on_unload(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
528 TRACE("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
530 /* Tests show that we have nothing more to do here */
532 if(pvaOut) {
533 V_VT(pvaOut) = VT_BOOL;
534 V_BOOL(pvaOut) = VARIANT_TRUE;
537 return S_OK;
540 static HRESULT exec_show_page_setup(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
542 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
543 return E_NOTIMPL;
546 static HRESULT exec_show_print(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
548 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
549 return E_NOTIMPL;
552 static HRESULT exec_close(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
554 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
555 return E_NOTIMPL;
558 static HRESULT exec_set_print_template(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
560 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
561 return E_NOTIMPL;
564 static HRESULT exec_get_print_template(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
566 FIXME("(%p)->(%ld %p %p)\n", doc, nCmdexecopt, pvaIn, pvaOut);
567 return E_NOTIMPL;
570 static HRESULT exec_optical_zoom(HTMLDocumentNode *doc, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
572 TRACE("(%p)->(%ld %s %p)\n", doc, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
574 if(pvaIn && V_VT(pvaIn) != VT_I4) {
575 FIXME("Unsupported argument %s\n", debugstr_variant(pvaIn));
576 return E_NOTIMPL;
579 if(pvaIn)
580 set_viewer_zoom(doc->browser, (float)V_I4(pvaIn)/100);
581 if(pvaOut) {
582 V_VT(pvaOut) = VT_I4;
583 V_I4(pvaOut) = get_viewer_zoom(doc->browser) * 100;
585 return S_OK;
588 static HRESULT query_mshtml_copy(HTMLDocumentNode *doc, OLECMD *cmd)
590 FIXME("(%p)\n", doc);
591 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
592 return S_OK;
595 static HRESULT exec_mshtml_copy(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
597 TRACE("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
599 if(doc->browser->usermode == EDITMODE)
600 return editor_exec_copy(doc, cmdexecopt, in, out);
602 do_ns_command(doc, NSCMD_COPY, NULL);
603 return S_OK;
606 static HRESULT query_mshtml_cut(HTMLDocumentNode *doc, OLECMD *cmd)
608 FIXME("(%p)\n", doc);
609 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
610 return S_OK;
613 static HRESULT exec_mshtml_cut(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
615 nsIClipboardCommands *clipboard_commands;
616 nsresult nsres;
618 TRACE("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
620 if(doc->browser->usermode == EDITMODE)
621 return editor_exec_cut(doc, cmdexecopt, in, out);
623 clipboard_commands = get_clipboard_commands(doc);
624 if(!clipboard_commands)
625 return E_UNEXPECTED;
627 nsres = nsIClipboardCommands_CutSelection(clipboard_commands);
628 nsIClipboardCommands_Release(clipboard_commands);
629 if(NS_FAILED(nsres)) {
630 ERR("Paste failed: %08lx\n", nsres);
631 return E_FAIL;
634 return S_OK;
637 static HRESULT query_mshtml_paste(HTMLDocumentNode *doc, OLECMD *cmd)
639 FIXME("(%p)\n", doc);
640 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
641 return S_OK;
644 static HRESULT exec_mshtml_paste(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
646 nsIClipboardCommands *clipboard_commands;
647 nsresult nsres;
649 TRACE("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
651 if(doc->browser->usermode == EDITMODE)
652 return editor_exec_paste(doc, cmdexecopt, in, out);
654 clipboard_commands = get_clipboard_commands(doc);
655 if(!clipboard_commands)
656 return E_UNEXPECTED;
658 nsres = nsIClipboardCommands_Paste(clipboard_commands);
659 nsIClipboardCommands_Release(clipboard_commands);
660 if(NS_FAILED(nsres)) {
661 ERR("Paste failed: %08lx\n", nsres);
662 return E_FAIL;
665 return S_OK;
668 static HRESULT query_selall_status(HTMLDocumentNode *doc, OLECMD *cmd)
670 TRACE("(%p)->(%p)\n", doc, cmd);
672 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
673 return S_OK;
676 static HRESULT exec_browsemode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
678 WARN("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
680 if(in || out)
681 FIXME("unsupported args\n");
683 doc->browser->usermode = BROWSEMODE;
685 return S_OK;
688 static HRESULT exec_editmode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
690 TRACE("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
692 if(in || out)
693 FIXME("unsupported args\n");
695 return setup_edit_mode(doc->browser->doc);
698 static HRESULT exec_htmleditmode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
700 FIXME("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
701 return S_OK;
704 static HRESULT exec_baselinefont3(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
706 FIXME("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
707 return S_OK;
710 static HRESULT exec_respectvisibility_indesign(HTMLDocumentNode *doc, DWORD cmdexecopt,
711 VARIANT *in, VARIANT *out)
713 TRACE("(%p)->(%lx %s %p)\n", doc, cmdexecopt, debugstr_variant(in), out);
715 /* This is turned on by default in Gecko. */
716 if(!in || V_VT(in) != VT_BOOL || !V_BOOL(in))
717 FIXME("Unsupported argument %s\n", debugstr_variant(in));
719 return S_OK;
722 static HRESULT query_enabled_stub(HTMLDocumentNode *doc, OLECMD *cmd)
724 switch(cmd->cmdID) {
725 case IDM_PRINT:
726 FIXME("CGID_MSHTML: IDM_PRINT\n");
727 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
728 break;
729 case IDM_BLOCKDIRLTR:
730 FIXME("CGID_MSHTML: IDM_BLOCKDIRLTR\n");
731 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
732 break;
733 case IDM_BLOCKDIRRTL:
734 FIXME("CGID_MSHTML: IDM_BLOCKDIRRTL\n");
735 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
736 break;
739 return S_OK;
742 static const struct {
743 OLECMDF cmdf;
744 HRESULT (*func)(HTMLDocumentNode*,DWORD,VARIANT*,VARIANT*);
745 } exec_table[] = {
746 {0},
747 { OLECMDF_SUPPORTED, exec_open }, /* OLECMDID_OPEN */
748 { OLECMDF_SUPPORTED, exec_new }, /* OLECMDID_NEW */
749 { OLECMDF_SUPPORTED, exec_save }, /* OLECMDID_SAVE */
750 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_save_as }, /* OLECMDID_SAVEAS */
751 { OLECMDF_SUPPORTED, exec_save_copy_as }, /* OLECMDID_SAVECOPYAS */
752 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_print }, /* OLECMDID_PRINT */
753 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_print_preview }, /* OLECMDID_PRINTPREVIEW */
754 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_page_setup }, /* OLECMDID_PAGESETUP */
755 { OLECMDF_SUPPORTED, exec_spell }, /* OLECMDID_SPELL */
756 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_properties }, /* OLECMDID_PROPERTIES */
757 { OLECMDF_SUPPORTED, exec_cut }, /* OLECMDID_CUT */
758 { OLECMDF_SUPPORTED, exec_copy }, /* OLECMDID_COPY */
759 { OLECMDF_SUPPORTED, exec_paste }, /* OLECMDID_PASTE */
760 { OLECMDF_SUPPORTED, exec_paste_special }, /* OLECMDID_PASTESPECIAL */
761 { OLECMDF_SUPPORTED, exec_undo }, /* OLECMDID_UNDO */
762 { OLECMDF_SUPPORTED, exec_rendo }, /* OLECMDID_REDO */
763 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_select_all }, /* OLECMDID_SELECTALL */
764 { OLECMDF_SUPPORTED, exec_clear_selection }, /* OLECMDID_CLEARSELECTION */
765 { OLECMDF_SUPPORTED, exec_zoom }, /* OLECMDID_ZOOM */
766 { OLECMDF_SUPPORTED, exec_get_zoom_range }, /* OLECMDID_GETZOOMRANGE */
767 {0},
768 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_refresh }, /* OLECMDID_REFRESH */
769 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_stop }, /* OLECMDID_STOP */
770 {0},{0},{0},{0},{0},{0},
771 { OLECMDF_SUPPORTED, exec_stop_download }, /* OLECMDID_STOPDOWNLOAD */
772 {0},
773 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_find }, /* OLECMDID_FIND */
774 { OLECMDF_SUPPORTED, exec_delete }, /* OLECMDID_DELETE */
775 {0},{0},
776 { OLECMDF_SUPPORTED, exec_enable_interaction }, /* OLECMDID_ENABLE_INTERACTION */
777 { OLECMDF_SUPPORTED, exec_on_unload }, /* OLECMDID_ONUNLOAD */
778 {0},{0},{0},{0},{0},
779 { OLECMDF_SUPPORTED, exec_show_page_setup }, /* OLECMDID_SHOWPAGESETUP */
780 { OLECMDF_SUPPORTED, exec_show_print }, /* OLECMDID_SHOWPRINT */
781 {0},{0},
782 { OLECMDF_SUPPORTED, exec_close }, /* OLECMDID_CLOSE */
783 {0},{0},{0},
784 { OLECMDF_SUPPORTED, exec_set_print_template }, /* OLECMDID_SETPRINTTEMPLATE */
785 { OLECMDF_SUPPORTED, exec_get_print_template }, /* OLECMDID_GETPRINTTEMPLATE */
786 {0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
787 { 0, /* not reported as supported */ exec_optical_zoom } /* OLECMDID_OPTICAL_ZOOM */
790 static const cmdtable_t base_cmds[] = {
791 {IDM_COPY, query_mshtml_copy, exec_mshtml_copy},
792 {IDM_PASTE, query_mshtml_paste, exec_mshtml_paste},
793 {IDM_CUT, query_mshtml_cut, exec_mshtml_cut},
794 {IDM_SELECTALL, query_selall_status, exec_select_all},
795 {IDM_BROWSEMODE, NULL, exec_browsemode},
796 {IDM_EDITMODE, NULL, exec_editmode},
797 {IDM_PRINT, query_enabled_stub, exec_print},
798 {IDM_HTMLEDITMODE, NULL, exec_htmleditmode},
799 {IDM_BASELINEFONT3, NULL, exec_baselinefont3},
800 {IDM_BLOCKDIRLTR, query_enabled_stub, NULL},
801 {IDM_BLOCKDIRRTL, query_enabled_stub, NULL},
802 {IDM_RESPECTVISIBILITY_INDESIGN, NULL, exec_respectvisibility_indesign},
803 {0,NULL,NULL}
806 static HRESULT WINAPI DocNodeOleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
808 HTMLDocumentNode *This = HTMLDocumentNode_from_IOleCommandTarget(iface);
809 return IHTMLDOMNode_QueryInterface(&This->node.IHTMLDOMNode_iface, riid, ppv);
812 static ULONG WINAPI DocNodeOleCommandTarget_AddRef(IOleCommandTarget *iface)
814 HTMLDocumentNode *This = HTMLDocumentNode_from_IOleCommandTarget(iface);
815 return IHTMLDOMNode_AddRef(&This->node.IHTMLDOMNode_iface);
818 static ULONG WINAPI DocNodeOleCommandTarget_Release(IOleCommandTarget *iface)
820 HTMLDocumentNode *This = HTMLDocumentNode_from_IOleCommandTarget(iface);
821 return IHTMLDOMNode_Release(&This->node.IHTMLDOMNode_iface);
824 static HRESULT query_from_table(HTMLDocumentNode *doc, const cmdtable_t *cmdtable, OLECMD *cmd)
826 const cmdtable_t *iter = cmdtable;
828 cmd->cmdf = 0;
830 while(iter->id && iter->id != cmd->cmdID)
831 iter++;
833 if(!iter->id || !iter->query)
834 return OLECMDERR_E_NOTSUPPORTED;
836 return iter->query(doc, cmd);
839 static HRESULT WINAPI DocNodeOleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
840 ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
842 HTMLDocumentNode *This = HTMLDocumentNode_from_IOleCommandTarget(iface);
843 HRESULT hres;
845 TRACE("(%p)->(%s %ld %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
847 if(pCmdText)
848 FIXME("Unsupported pCmdText\n");
849 if(!This->browser)
850 return E_UNEXPECTED;
851 if(!cCmds)
852 return S_OK;
854 if(!pguidCmdGroup) {
855 ULONG i;
857 for(i=0; i<cCmds; i++) {
858 if(prgCmds[i].cmdID < OLECMDID_OPEN || prgCmds[i].cmdID >= ARRAY_SIZE(exec_table)) {
859 WARN("Unsupported cmdID = %ld\n", prgCmds[i].cmdID);
860 prgCmds[i].cmdf = 0;
861 }else {
862 if(prgCmds[i].cmdID == OLECMDID_OPEN || prgCmds[i].cmdID == OLECMDID_NEW) {
863 IOleCommandTarget *cmdtrg = NULL;
864 OLECMD olecmd;
866 prgCmds[i].cmdf = OLECMDF_SUPPORTED;
867 if(This->doc_obj->client) {
868 hres = IOleClientSite_QueryInterface(This->doc_obj->client, &IID_IOleCommandTarget,
869 (void**)&cmdtrg);
870 if(SUCCEEDED(hres)) {
871 olecmd.cmdID = prgCmds[i].cmdID;
872 olecmd.cmdf = 0;
874 hres = IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &olecmd, NULL);
875 if(SUCCEEDED(hres) && olecmd.cmdf)
876 prgCmds[i].cmdf = olecmd.cmdf;
878 }else {
879 ERR("This->client == NULL, native would crash\n");
881 }else {
882 prgCmds[i].cmdf = exec_table[prgCmds[i].cmdID].cmdf;
883 TRACE("cmdID = %ld returning %lx\n", prgCmds[i].cmdID, prgCmds[i].cmdf);
888 return (prgCmds[cCmds-1].cmdf & OLECMDF_SUPPORTED) ? S_OK : OLECMDERR_E_NOTSUPPORTED;
891 if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
892 ULONG i;
894 for(i=0; i<cCmds; i++) {
895 hres = query_from_table(This, base_cmds, prgCmds+i);
896 if(hres == OLECMDERR_E_NOTSUPPORTED)
897 hres = query_from_table(This, editmode_cmds, prgCmds+i);
898 if(hres == OLECMDERR_E_NOTSUPPORTED)
899 FIXME("CGID_MSHTML: unsupported cmdID %ld\n", prgCmds[i].cmdID);
902 return (prgCmds[cCmds-1].cmdf & OLECMDF_SUPPORTED) ? S_OK : OLECMDERR_E_NOTSUPPORTED;
905 FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
906 return OLECMDERR_E_UNKNOWNGROUP;
909 static HRESULT exec_from_table(HTMLDocumentNode *doc, const cmdtable_t *cmdtable, DWORD cmdid,
910 DWORD cmdexecopt, VARIANT *in, VARIANT *out)
912 const cmdtable_t *iter = cmdtable;
914 while(iter->id && iter->id != cmdid)
915 iter++;
917 if(!iter->id || !iter->exec)
918 return OLECMDERR_E_NOTSUPPORTED;
920 return iter->exec(doc, cmdexecopt, in, out);
923 static HRESULT WINAPI DocNodeOleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
924 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
926 HTMLDocumentNode *This = HTMLDocumentNode_from_IOleCommandTarget(iface);
928 TRACE("(%p)->(%s %ld %ld %s %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, wine_dbgstr_variant(pvaIn), pvaOut);
930 if(!This->browser)
931 return E_UNEXPECTED;
933 if(!pguidCmdGroup) {
934 if(nCmdID < OLECMDID_OPEN || nCmdID >= ARRAY_SIZE(exec_table) || !exec_table[nCmdID].func) {
935 WARN("Unsupported cmdID = %ld\n", nCmdID);
936 return OLECMDERR_E_NOTSUPPORTED;
939 return exec_table[nCmdID].func(This, nCmdexecopt, pvaIn, pvaOut);
940 }else if(IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) {
941 FIXME("unsupported nCmdID %ld of CGID_Explorer group\n", nCmdID);
942 TRACE("%p %p\n", pvaIn, pvaOut);
943 return OLECMDERR_E_NOTSUPPORTED;
944 }else if(IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup)) {
945 FIXME("unsupported nCmdID %ld of CGID_ShellDocView group\n", nCmdID);
946 return OLECMDERR_E_NOTSUPPORTED;
947 }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
948 HRESULT hres = exec_from_table(This, base_cmds, nCmdID, nCmdexecopt, pvaIn, pvaOut);
949 if(hres == OLECMDERR_E_NOTSUPPORTED)
950 hres = exec_from_table(This, editmode_cmds, nCmdID,
951 nCmdexecopt, pvaIn, pvaOut);
952 if(hres == OLECMDERR_E_NOTSUPPORTED)
953 FIXME("unsupported nCmdID %ld of CGID_MSHTML group\n", nCmdID);
955 return hres;
958 FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
959 return OLECMDERR_E_UNKNOWNGROUP;
962 static const IOleCommandTargetVtbl DocNodeOleCommandTargetVtbl = {
963 DocNodeOleCommandTarget_QueryInterface,
964 DocNodeOleCommandTarget_AddRef,
965 DocNodeOleCommandTarget_Release,
966 DocNodeOleCommandTarget_QueryStatus,
967 DocNodeOleCommandTarget_Exec
970 static HRESULT WINAPI DocObjOleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
972 HTMLDocumentObj *This = HTMLDocumentObj_from_IOleCommandTarget(iface);
973 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
976 static ULONG WINAPI DocObjOleCommandTarget_AddRef(IOleCommandTarget *iface)
978 HTMLDocumentObj *This = HTMLDocumentObj_from_IOleCommandTarget(iface);
979 return IUnknown_AddRef(This->outer_unk);
982 static ULONG WINAPI DocObjOleCommandTarget_Release(IOleCommandTarget *iface)
984 HTMLDocumentObj *This = HTMLDocumentObj_from_IOleCommandTarget(iface);
985 return IUnknown_Release(This->outer_unk);
988 static HRESULT WINAPI DocObjOleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
989 ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
991 HTMLDocumentObj *This = HTMLDocumentObj_from_IOleCommandTarget(iface);
993 return IOleCommandTarget_QueryStatus(&This->doc_node->IOleCommandTarget_iface,
994 pguidCmdGroup, cCmds, prgCmds, pCmdText);
997 static HRESULT WINAPI DocObjOleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
998 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1000 HTMLDocumentObj *This = HTMLDocumentObj_from_IOleCommandTarget(iface);
1002 return IOleCommandTarget_Exec(&This->doc_node->IOleCommandTarget_iface,
1003 pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
1006 static const IOleCommandTargetVtbl DocObjOleCommandTargetVtbl = {
1007 DocObjOleCommandTarget_QueryInterface,
1008 DocObjOleCommandTarget_AddRef,
1009 DocObjOleCommandTarget_Release,
1010 DocObjOleCommandTarget_QueryStatus,
1011 DocObjOleCommandTarget_Exec
1014 void show_context_menu(HTMLDocumentObj *This, DWORD dwID, POINT *ppt, IDispatch *elem)
1016 HMENU menu_res, menu;
1017 DWORD cmdid;
1019 if(This->hostui && S_OK == IDocHostUIHandler_ShowContextMenu(This->hostui,
1020 dwID, ppt, (IUnknown*)&This->IOleCommandTarget_iface, elem))
1021 return;
1023 menu_res = LoadMenuW(get_shdoclc(), MAKEINTRESOURCEW(IDR_BROWSE_CONTEXT_MENU));
1024 menu = GetSubMenu(menu_res, dwID);
1026 cmdid = TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
1027 ppt->x, ppt->y, 0, This->hwnd, NULL);
1028 DestroyMenu(menu_res);
1030 if(cmdid)
1031 IOleCommandTarget_Exec(&This->IOleCommandTarget_iface, &CGID_MSHTML, cmdid, 0,
1032 NULL, NULL);
1035 void HTMLDocumentNode_OleCmd_Init(HTMLDocumentNode *This)
1037 This->IOleCommandTarget_iface.lpVtbl = &DocNodeOleCommandTargetVtbl;
1040 void HTMLDocumentObj_OleCmd_Init(HTMLDocumentObj *This)
1042 This->IOleCommandTarget_iface.lpVtbl = &DocObjOleCommandTargetVtbl;