xref: /reactos/dll/win32/mshtml/olecmd.c (revision a050be08)
1 /*
2  * Copyright 2005-2007 Jacek Caban for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18 
19 #include "mshtml_private.h"
20 
21 #define NSCMD_COPY "cmd_copy"
22 #define NSCMD_SELECTALL           "cmd_selectAll"
23 
do_ns_command(HTMLDocument * This,const char * cmd,nsICommandParams * nsparam)24 void do_ns_command(HTMLDocument *This, const char *cmd, nsICommandParams *nsparam)
25 {
26     nsICommandManager *cmdmgr;
27     nsresult nsres;
28 
29     TRACE("(%p)\n", This);
30 
31     if(!This->doc_obj || !This->doc_obj->nscontainer)
32         return;
33 
34     nsres = get_nsinterface((nsISupports*)This->doc_obj->nscontainer->webbrowser, &IID_nsICommandManager, (void**)&cmdmgr);
35     if(NS_FAILED(nsres)) {
36         ERR("Could not get nsICommandManager: %08x\n", nsres);
37         return;
38     }
39 
40     nsres = nsICommandManager_DoCommand(cmdmgr, cmd, nsparam, This->window->nswindow);
41     if(NS_FAILED(nsres))
42         ERR("DoCommand(%s) failed: %08x\n", debugstr_a(cmd), nsres);
43 
44     nsICommandManager_Release(cmdmgr);
45 }
46 
get_clipboard_commands(HTMLDocument * doc)47 static nsIClipboardCommands *get_clipboard_commands(HTMLDocument *doc)
48 {
49     nsIClipboardCommands *clipboard_commands;
50     nsIDocShell *doc_shell;
51     nsresult nsres;
52 
53     nsres = get_nsinterface((nsISupports*)doc->window->nswindow, &IID_nsIDocShell, (void**)&doc_shell);
54     if(NS_FAILED(nsres)) {
55         ERR("Could not get nsIDocShell interface\n");
56         return NULL;
57     }
58 
59     nsres = nsIDocShell_QueryInterface(doc_shell, &IID_nsIClipboardCommands, (void**)&clipboard_commands);
60     nsIDocShell_Release(doc_shell);
61     if(NS_FAILED(nsres)) {
62         ERR("Could not get nsIClipboardCommands interface\n");
63         return NULL;
64     }
65 
66     return clipboard_commands;
67 }
68 
69 /**********************************************************
70  * IOleCommandTarget implementation
71  */
72 
impl_from_IOleCommandTarget(IOleCommandTarget * iface)73 static inline HTMLDocument *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
74 {
75     return CONTAINING_RECORD(iface, HTMLDocument, IOleCommandTarget_iface);
76 }
77 
exec_open(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)78 static HRESULT exec_open(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
79 {
80     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
81     return E_NOTIMPL;
82 }
83 
exec_new(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)84 static HRESULT exec_new(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
85 {
86     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
87     return E_NOTIMPL;
88 }
89 
exec_save(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)90 static HRESULT exec_save(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
91 {
92     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
93     return E_NOTIMPL;
94 }
95 
exec_save_as(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)96 static HRESULT exec_save_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
97 {
98     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
99     return E_NOTIMPL;
100 }
101 
exec_save_copy_as(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)102 static HRESULT exec_save_copy_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
103 {
104     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
105     return E_NOTIMPL;
106 }
107 
set_head_text(nsIPrintSettings * settings,LPCWSTR template,BOOL head,int pos)108 static nsresult set_head_text(nsIPrintSettings *settings, LPCWSTR template, BOOL head, int pos)
109 {
110     if(head) {
111         switch(pos) {
112         case 0:
113             return nsIPrintSettings_SetHeaderStrLeft(settings, template);
114         case 1:
115             return nsIPrintSettings_SetHeaderStrRight(settings, template);
116         case 2:
117             return nsIPrintSettings_SetHeaderStrCenter(settings, template);
118         }
119     }else {
120         switch(pos) {
121         case 0:
122             return nsIPrintSettings_SetFooterStrLeft(settings, template);
123         case 1:
124             return nsIPrintSettings_SetFooterStrRight(settings, template);
125         case 2:
126             return nsIPrintSettings_SetFooterStrCenter(settings, template);
127         }
128     }
129 
130     return NS_OK;
131 }
132 
set_print_template(nsIPrintSettings * settings,LPCWSTR template,BOOL head)133 static void set_print_template(nsIPrintSettings *settings, LPCWSTR template, BOOL head)
134 {
135     PRUnichar nstemplate[200]; /* FIXME: Use dynamic allocation */
136     PRUnichar *p = nstemplate;
137     LPCWSTR ptr=template;
138     int pos=0;
139 
140     while(*ptr) {
141         if(*ptr != '&') {
142             *p++ = *ptr++;
143             continue;
144         }
145 
146         switch(*++ptr) {
147         case '&':
148             *p++ = '&';
149             *p++ = '&';
150             ptr++;
151             break;
152         case 'b': /* change align */
153             ptr++;
154             *p = 0;
155             set_head_text(settings, nstemplate, head, pos);
156             p = nstemplate;
157             pos++;
158             break;
159         case 'd': { /* short date */
160             SYSTEMTIME systime;
161             GetLocalTime(&systime);
162             GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &systime, NULL, p,
163                     sizeof(nstemplate)-(p-nstemplate)*sizeof(WCHAR));
164             p += strlenW(p);
165             ptr++;
166             break;
167         }
168         case 'p': /* page number */
169             *p++ = '&';
170             *p++ = 'P';
171             ptr++;
172             break;
173         case 'P': /* page count */
174             *p++ = '?'; /* FIXME */
175             ptr++;
176             break;
177         case 'u':
178             *p++ = '&';
179             *p++ = 'U';
180             ptr++;
181             break;
182         case 'w':
183             /* FIXME: set window title */
184             ptr++;
185             break;
186         default:
187             *p++ = '&';
188             *p++ = *ptr++;
189         }
190     }
191 
192     *p = 0;
193     set_head_text(settings, nstemplate, head, pos);
194 
195     while(++pos < 3)
196         set_head_text(settings, p, head, pos);
197 }
198 
set_default_templates(nsIPrintSettings * settings)199 static void set_default_templates(nsIPrintSettings *settings)
200 {
201     WCHAR buf[64];
202 
203     static const PRUnichar empty[] = {0};
204 
205     nsIPrintSettings_SetHeaderStrLeft(settings, empty);
206     nsIPrintSettings_SetHeaderStrRight(settings, empty);
207     nsIPrintSettings_SetHeaderStrCenter(settings, empty);
208     nsIPrintSettings_SetFooterStrLeft(settings, empty);
209     nsIPrintSettings_SetFooterStrRight(settings, empty);
210     nsIPrintSettings_SetFooterStrCenter(settings, empty);
211 
212     if(LoadStringW(get_shdoclc(), IDS_PRINT_HEADER_TEMPLATE, buf,
213                    sizeof(buf)/sizeof(WCHAR)))
214         set_print_template(settings, buf, TRUE);
215 
216 
217     if(LoadStringW(get_shdoclc(), IDS_PRINT_FOOTER_TEMPLATE, buf,
218                    sizeof(buf)/sizeof(WCHAR)))
219         set_print_template(settings, buf, FALSE);
220 
221 }
222 
exec_print(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)223 static HRESULT exec_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
224 {
225     nsIWebBrowserPrint *nsprint;
226     nsIPrintSettings *settings;
227     nsresult nsres;
228 
229     TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
230 
231     if(pvaOut)
232         FIXME("unsupported pvaOut\n");
233 
234     if(!This->doc_obj->nscontainer)
235         return S_OK;
236 
237     nsres = get_nsinterface((nsISupports*)This->doc_obj->nscontainer->webbrowser, &IID_nsIWebBrowserPrint,
238             (void**)&nsprint);
239     if(NS_FAILED(nsres)) {
240         ERR("Could not get nsIWebBrowserPrint: %08x\n", nsres);
241         return S_OK;
242     }
243 
244 #ifdef __REACTOS__
245     // returning here fixes CORE-16884. Maybe use this until printing works.
246     ERR("Aborting print, to work around CORE-16884\n");
247     nsIWebBrowserPrint_Release(nsprint);
248     return S_OK;
249 #endif
250 
251     nsres = nsIWebBrowserPrint_GetGlobalPrintSettings(nsprint, &settings);
252     if(NS_FAILED(nsres))
253         ERR("GetCurrentPrintSettings failed: %08x\n", nsres);
254 
255     set_default_templates(settings);
256 
257     if(pvaIn) {
258         switch(V_VT(pvaIn)) {
259         case VT_BYREF|VT_ARRAY: {
260             VARIANT *opts;
261             DWORD opts_cnt;
262 
263             if(V_ARRAY(pvaIn)->cDims != 1)
264                 WARN("cDims = %d\n", V_ARRAY(pvaIn)->cDims);
265 
266             SafeArrayAccessData(V_ARRAY(pvaIn), (void**)&opts);
267             opts_cnt = V_ARRAY(pvaIn)->rgsabound[0].cElements;
268 
269             if(opts_cnt >= 1) {
270                 switch(V_VT(opts)) {
271                 case VT_BSTR:
272                     TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts)));
273                     set_print_template(settings, V_BSTR(opts), TRUE);
274                     break;
275                 case VT_NULL:
276                     break;
277                 default:
278                     WARN("opts = %s\n", debugstr_variant(opts));
279                 }
280             }
281 
282             if(opts_cnt >= 2) {
283                 switch(V_VT(opts+1)) {
284                 case VT_BSTR:
285                     TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts+1)));
286                     set_print_template(settings, V_BSTR(opts+1), FALSE);
287                     break;
288                 case VT_NULL:
289                     break;
290                 default:
291                     WARN("opts[1] = %s\n", debugstr_variant(opts+1));
292                 }
293             }
294 
295             if(opts_cnt >= 3)
296                 FIXME("Unsupported opts_cnt %d\n", opts_cnt);
297 
298             SafeArrayUnaccessData(V_ARRAY(pvaIn));
299             break;
300         }
301         default:
302             FIXME("unsupported arg %s\n", debugstr_variant(pvaIn));
303         }
304     }
305 
306     nsres = nsIWebBrowserPrint_Print(nsprint, settings, NULL);
307     if(NS_FAILED(nsres))
308         ERR("Print failed: %08x\n", nsres);
309 
310     nsIWebBrowserPrint_Release(nsprint);
311 
312     return S_OK;
313 }
314 
exec_print_preview(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)315 static HRESULT exec_print_preview(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
316 {
317     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
318     return E_NOTIMPL;
319 }
320 
exec_page_setup(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)321 static HRESULT exec_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
322 {
323     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
324     return E_NOTIMPL;
325 }
326 
exec_spell(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)327 static HRESULT exec_spell(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
328 {
329     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
330     return E_NOTIMPL;
331 }
332 
exec_properties(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)333 static HRESULT exec_properties(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
334 {
335     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
336     return E_NOTIMPL;
337 }
338 
exec_cut(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)339 static HRESULT exec_cut(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
340 {
341     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
342     return E_NOTIMPL;
343 }
344 
exec_copy(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)345 static HRESULT exec_copy(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
346 {
347     TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
348 
349     do_ns_command(This, NSCMD_COPY, NULL);
350     return S_OK;
351 }
352 
exec_paste(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)353 static HRESULT exec_paste(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
354 {
355     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
356     return E_NOTIMPL;
357 }
358 
exec_paste_special(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)359 static HRESULT exec_paste_special(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
360 {
361     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
362     return E_NOTIMPL;
363 }
364 
exec_undo(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)365 static HRESULT exec_undo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
366 {
367     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
368     return E_NOTIMPL;
369 }
370 
exec_rendo(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)371 static HRESULT exec_rendo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
372 {
373     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
374     return E_NOTIMPL;
375 }
376 
exec_select_all(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * in,VARIANT * out)377 static HRESULT exec_select_all(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *in, VARIANT *out)
378 {
379     TRACE("(%p)\n", This);
380 
381     if(in || out)
382         FIXME("unsupported args\n");
383 
384     if(This->doc_obj->nscontainer)
385         do_ns_command(This, NSCMD_SELECTALL, NULL);
386 
387     update_doc(This, UPDATE_UI);
388     return S_OK;
389 }
390 
exec_clear_selection(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)391 static HRESULT exec_clear_selection(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
392 {
393     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
394     return E_NOTIMPL;
395 }
396 
exec_zoom(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)397 static HRESULT exec_zoom(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
398 {
399     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
400     return E_NOTIMPL;
401 }
402 
exec_get_zoom_range(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)403 static HRESULT exec_get_zoom_range(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
404 {
405     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
406     return E_NOTIMPL;
407 }
408 
409 typedef struct {
410     task_t header;
411     HTMLOuterWindow *window;
412 }refresh_task_t;
413 
refresh_proc(task_t * _task)414 static void refresh_proc(task_t *_task)
415 {
416     refresh_task_t *task = (refresh_task_t*)_task;
417     HTMLOuterWindow *window = task->window;
418 
419     TRACE("%p\n", window);
420 
421     window->readystate = READYSTATE_UNINITIALIZED;
422 
423     if(window->doc_obj && window->doc_obj->client_cmdtrg) {
424         VARIANT var;
425 
426         V_VT(&var) = VT_I4;
427         V_I4(&var) = 0;
428         IOleCommandTarget_Exec(window->doc_obj->client_cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL);
429     }
430 
431     load_uri(task->window, task->window->uri, BINDING_REFRESH|BINDING_NOFRAG);
432 }
433 
refresh_destr(task_t * _task)434 static void refresh_destr(task_t *_task)
435 {
436     refresh_task_t *task = (refresh_task_t*)_task;
437 
438     IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface);
439     heap_free(task);
440 }
441 
exec_refresh(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)442 static HRESULT exec_refresh(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
443 {
444     refresh_task_t *task;
445     HRESULT hres;
446 
447     TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
448 
449     if(This->doc_obj->client) {
450         IOleCommandTarget *olecmd;
451 
452         hres = IOleClientSite_QueryInterface(This->doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd);
453         if(SUCCEEDED(hres)) {
454             hres = IOleCommandTarget_Exec(olecmd, &CGID_DocHostCommandHandler, 2300, nCmdexecopt, pvaIn, pvaOut);
455             IOleCommandTarget_Release(olecmd);
456             if(SUCCEEDED(hres))
457                 return S_OK;
458         }
459     }
460 
461     if(!This->window)
462         return E_UNEXPECTED;
463 
464     task = heap_alloc(sizeof(*task));
465     if(!task)
466         return E_OUTOFMEMORY;
467 
468     IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface);
469     task->window = This->window;
470 
471     return push_task(&task->header, refresh_proc, refresh_destr, This->window->task_magic);
472 }
473 
exec_stop(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)474 static HRESULT exec_stop(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
475 {
476     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
477     return E_NOTIMPL;
478 }
479 
exec_stop_download(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)480 static HRESULT exec_stop_download(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
481 {
482     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
483     return E_NOTIMPL;
484 }
485 
exec_find(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)486 static HRESULT exec_find(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
487 {
488     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
489     return E_NOTIMPL;
490 }
491 
exec_delete(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)492 static HRESULT exec_delete(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
493 {
494     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
495     return E_NOTIMPL;
496 }
497 
exec_enable_interaction(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)498 static HRESULT exec_enable_interaction(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
499 {
500     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
501     return E_NOTIMPL;
502 }
503 
exec_on_unload(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)504 static HRESULT exec_on_unload(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
505 {
506     TRACE("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
507 
508     /* Tests show that we have nothing more to do here */
509 
510     if(pvaOut) {
511         V_VT(pvaOut) = VT_BOOL;
512         V_BOOL(pvaOut) = VARIANT_TRUE;
513     }
514 
515     return S_OK;
516 }
517 
exec_show_page_setup(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)518 static HRESULT exec_show_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
519 {
520     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
521     return E_NOTIMPL;
522 }
523 
exec_show_print(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)524 static HRESULT exec_show_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
525 {
526     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
527     return E_NOTIMPL;
528 }
529 
exec_close(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)530 static HRESULT exec_close(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
531 {
532     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
533     return E_NOTIMPL;
534 }
535 
exec_set_print_template(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)536 static HRESULT exec_set_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
537 {
538     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
539     return E_NOTIMPL;
540 }
541 
exec_get_print_template(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)542 static HRESULT exec_get_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
543 {
544     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
545     return E_NOTIMPL;
546 }
547 
exec_optical_zoom(HTMLDocument * This,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)548 static HRESULT exec_optical_zoom(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
549 {
550     TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
551 
552     if(!pvaIn || V_VT(pvaIn) != VT_I4) {
553         FIXME("Unsupported argument %s\n", debugstr_variant(pvaIn));
554         return E_NOTIMPL;
555     }
556 
557     set_viewer_zoom(This->doc_obj->nscontainer, (float)V_I4(pvaIn)/100);
558     return S_OK;
559 }
560 
query_mshtml_copy(HTMLDocument * This,OLECMD * cmd)561 static HRESULT query_mshtml_copy(HTMLDocument *This, OLECMD *cmd)
562 {
563     FIXME("(%p)\n", This);
564     cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
565     return S_OK;
566 }
567 
exec_mshtml_copy(HTMLDocument * This,DWORD cmdexecopt,VARIANT * in,VARIANT * out)568 static HRESULT exec_mshtml_copy(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
569 {
570     TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
571 
572     if(This->doc_obj->usermode == EDITMODE)
573         return editor_exec_copy(This, cmdexecopt, in, out);
574 
575     do_ns_command(This, NSCMD_COPY, NULL);
576     return S_OK;
577 }
578 
query_mshtml_cut(HTMLDocument * This,OLECMD * cmd)579 static HRESULT query_mshtml_cut(HTMLDocument *This, OLECMD *cmd)
580 {
581     FIXME("(%p)\n", This);
582     cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
583     return S_OK;
584 }
585 
exec_mshtml_cut(HTMLDocument * This,DWORD cmdexecopt,VARIANT * in,VARIANT * out)586 static HRESULT exec_mshtml_cut(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
587 {
588     nsIClipboardCommands *clipboard_commands;
589     nsresult nsres;
590 
591     TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
592 
593     if(This->doc_obj->usermode == EDITMODE)
594         return editor_exec_cut(This, cmdexecopt, in, out);
595 
596     clipboard_commands = get_clipboard_commands(This);
597     if(!clipboard_commands)
598         return E_UNEXPECTED;
599 
600     nsres = nsIClipboardCommands_CutSelection(clipboard_commands);
601     nsIClipboardCommands_Release(clipboard_commands);
602     if(NS_FAILED(nsres)) {
603         ERR("Paste failed: %08x\n", nsres);
604         return E_FAIL;
605     }
606 
607     return S_OK;
608 }
609 
query_mshtml_paste(HTMLDocument * This,OLECMD * cmd)610 static HRESULT query_mshtml_paste(HTMLDocument *This, OLECMD *cmd)
611 {
612     FIXME("(%p)\n", This);
613     cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
614     return S_OK;
615 }
616 
exec_mshtml_paste(HTMLDocument * This,DWORD cmdexecopt,VARIANT * in,VARIANT * out)617 static HRESULT exec_mshtml_paste(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
618 {
619     nsIClipboardCommands *clipboard_commands;
620     nsresult nsres;
621 
622     TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
623 
624     if(This->doc_obj->usermode == EDITMODE)
625         return editor_exec_paste(This, cmdexecopt, in, out);
626 
627     clipboard_commands = get_clipboard_commands(This);
628     if(!clipboard_commands)
629         return E_UNEXPECTED;
630 
631     nsres = nsIClipboardCommands_Paste(clipboard_commands);
632     nsIClipboardCommands_Release(clipboard_commands);
633     if(NS_FAILED(nsres)) {
634         ERR("Paste failed: %08x\n", nsres);
635         return E_FAIL;
636     }
637 
638     return S_OK;
639 }
640 
query_selall_status(HTMLDocument * This,OLECMD * cmd)641 static HRESULT query_selall_status(HTMLDocument *This, OLECMD *cmd)
642 {
643     TRACE("(%p)->(%p)\n", This, cmd);
644 
645     cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
646     return S_OK;
647 }
648 
exec_browsemode(HTMLDocument * This,DWORD cmdexecopt,VARIANT * in,VARIANT * out)649 static HRESULT exec_browsemode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
650 {
651     WARN("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
652 
653     if(in || out)
654         FIXME("unsupported args\n");
655 
656     This->doc_obj->usermode = BROWSEMODE;
657 
658     return S_OK;
659 }
660 
exec_editmode(HTMLDocument * This,DWORD cmdexecopt,VARIANT * in,VARIANT * out)661 static HRESULT exec_editmode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
662 {
663     TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
664 
665     if(in || out)
666         FIXME("unsupported args\n");
667 
668     return setup_edit_mode(This->doc_obj);
669 }
670 
exec_htmleditmode(HTMLDocument * This,DWORD cmdexecopt,VARIANT * in,VARIANT * out)671 static HRESULT exec_htmleditmode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
672 {
673     FIXME("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
674     return S_OK;
675 }
676 
exec_baselinefont3(HTMLDocument * This,DWORD cmdexecopt,VARIANT * in,VARIANT * out)677 static HRESULT exec_baselinefont3(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
678 {
679     FIXME("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
680     return S_OK;
681 }
682 
exec_respectvisibility_indesign(HTMLDocument * This,DWORD cmdexecopt,VARIANT * in,VARIANT * out)683 static HRESULT exec_respectvisibility_indesign(HTMLDocument *This, DWORD cmdexecopt,
684         VARIANT *in, VARIANT *out)
685 {
686     TRACE("(%p)->(%x %s %p)\n", This, cmdexecopt, debugstr_variant(in), out);
687 
688     /* This is turned on by default in Gecko. */
689     if(!in || V_VT(in) != VT_BOOL || !V_BOOL(in))
690         FIXME("Unsupported argument %s\n", debugstr_variant(in));
691 
692     return S_OK;
693 }
694 
query_enabled_stub(HTMLDocument * This,OLECMD * cmd)695 static HRESULT query_enabled_stub(HTMLDocument *This, OLECMD *cmd)
696 {
697     switch(cmd->cmdID) {
698     case IDM_PRINT:
699         FIXME("CGID_MSHTML: IDM_PRINT\n");
700         cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
701         break;
702     case IDM_BLOCKDIRLTR:
703         FIXME("CGID_MSHTML: IDM_BLOCKDIRLTR\n");
704         cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
705         break;
706     case IDM_BLOCKDIRRTL:
707         FIXME("CGID_MSHTML: IDM_BLOCKDIRRTL\n");
708         cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
709         break;
710     }
711 
712     return S_OK;
713 }
714 
715 static const struct {
716     OLECMDF cmdf;
717     HRESULT (*func)(HTMLDocument*,DWORD,VARIANT*,VARIANT*);
718 } exec_table[] = {
719     {0},
720     { OLECMDF_SUPPORTED,                  exec_open                 }, /* OLECMDID_OPEN */
721     { OLECMDF_SUPPORTED,                  exec_new                  }, /* OLECMDID_NEW */
722     { OLECMDF_SUPPORTED,                  exec_save                 }, /* OLECMDID_SAVE */
723     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_save_as              }, /* OLECMDID_SAVEAS */
724     { OLECMDF_SUPPORTED,                  exec_save_copy_as         }, /* OLECMDID_SAVECOPYAS */
725     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_print                }, /* OLECMDID_PRINT */
726     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_print_preview        }, /* OLECMDID_PRINTPREVIEW */
727     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_page_setup           }, /* OLECMDID_PAGESETUP */
728     { OLECMDF_SUPPORTED,                  exec_spell                }, /* OLECMDID_SPELL */
729     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_properties           }, /* OLECMDID_PROPERTIES */
730     { OLECMDF_SUPPORTED,                  exec_cut                  }, /* OLECMDID_CUT */
731     { OLECMDF_SUPPORTED,                  exec_copy                 }, /* OLECMDID_COPY */
732     { OLECMDF_SUPPORTED,                  exec_paste                }, /* OLECMDID_PASTE */
733     { OLECMDF_SUPPORTED,                  exec_paste_special        }, /* OLECMDID_PASTESPECIAL */
734     { OLECMDF_SUPPORTED,                  exec_undo                 }, /* OLECMDID_UNDO */
735     { OLECMDF_SUPPORTED,                  exec_rendo                }, /* OLECMDID_REDO */
736     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_select_all           }, /* OLECMDID_SELECTALL */
737     { OLECMDF_SUPPORTED,                  exec_clear_selection      }, /* OLECMDID_CLEARSELECTION */
738     { OLECMDF_SUPPORTED,                  exec_zoom                 }, /* OLECMDID_ZOOM */
739     { OLECMDF_SUPPORTED,                  exec_get_zoom_range       }, /* OLECMDID_GETZOOMRANGE */
740     {0},
741     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_refresh              }, /* OLECMDID_REFRESH */
742     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_stop                 }, /* OLECMDID_STOP */
743     {0},{0},{0},{0},{0},{0},
744     { OLECMDF_SUPPORTED,                  exec_stop_download        }, /* OLECMDID_STOPDOWNLOAD */
745     {0},
746     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_find                 }, /* OLECMDID_FIND */
747     { OLECMDF_SUPPORTED,                  exec_delete               }, /* OLECMDID_DELETE */
748     {0},{0},
749     { OLECMDF_SUPPORTED,                  exec_enable_interaction   }, /* OLECMDID_ENABLE_INTERACTION */
750     { OLECMDF_SUPPORTED,                  exec_on_unload            }, /* OLECMDID_ONUNLOAD */
751     {0},{0},{0},{0},{0},
752     { OLECMDF_SUPPORTED,                  exec_show_page_setup      }, /* OLECMDID_SHOWPAGESETUP */
753     { OLECMDF_SUPPORTED,                  exec_show_print           }, /* OLECMDID_SHOWPRINT */
754     {0},{0},
755     { OLECMDF_SUPPORTED,                  exec_close                }, /* OLECMDID_CLOSE */
756     {0},{0},{0},
757     { OLECMDF_SUPPORTED,                  exec_set_print_template   }, /* OLECMDID_SETPRINTTEMPLATE */
758     { OLECMDF_SUPPORTED,                  exec_get_print_template   }, /* OLECMDID_GETPRINTTEMPLATE */
759     {0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
760     { 0, /* not reported as supported */  exec_optical_zoom         }  /* OLECMDID_OPTICAL_ZOOM */
761 };
762 
763 static const cmdtable_t base_cmds[] = {
764     {IDM_COPY,             query_mshtml_copy,     exec_mshtml_copy},
765     {IDM_PASTE,            query_mshtml_paste,    exec_mshtml_paste},
766     {IDM_CUT,              query_mshtml_cut,      exec_mshtml_cut},
767     {IDM_SELECTALL,        query_selall_status,   exec_select_all},
768     {IDM_BROWSEMODE,       NULL,                  exec_browsemode},
769     {IDM_EDITMODE,         NULL,                  exec_editmode},
770     {IDM_PRINT,            query_enabled_stub,    exec_print},
771     {IDM_HTMLEDITMODE,     NULL,                  exec_htmleditmode},
772     {IDM_BASELINEFONT3,    NULL,                  exec_baselinefont3},
773     {IDM_BLOCKDIRLTR,      query_enabled_stub,    NULL},
774     {IDM_BLOCKDIRRTL,      query_enabled_stub,    NULL},
775     {IDM_RESPECTVISIBILITY_INDESIGN, NULL,        exec_respectvisibility_indesign},
776     {0,NULL,NULL}
777 };
778 
OleCommandTarget_QueryInterface(IOleCommandTarget * iface,REFIID riid,void ** ppv)779 static HRESULT WINAPI OleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
780 {
781     HTMLDocument *This = impl_from_IOleCommandTarget(iface);
782     return htmldoc_query_interface(This, riid, ppv);
783 }
784 
OleCommandTarget_AddRef(IOleCommandTarget * iface)785 static ULONG WINAPI OleCommandTarget_AddRef(IOleCommandTarget *iface)
786 {
787     HTMLDocument *This = impl_from_IOleCommandTarget(iface);
788     return htmldoc_addref(This);
789 }
790 
OleCommandTarget_Release(IOleCommandTarget * iface)791 static ULONG WINAPI OleCommandTarget_Release(IOleCommandTarget *iface)
792 {
793     HTMLDocument *This = impl_from_IOleCommandTarget(iface);
794     return htmldoc_release(This);
795 }
796 
query_from_table(HTMLDocument * This,const cmdtable_t * cmdtable,OLECMD * cmd)797 static HRESULT query_from_table(HTMLDocument *This, const cmdtable_t *cmdtable, OLECMD *cmd)
798 {
799     const cmdtable_t *iter = cmdtable;
800 
801     cmd->cmdf = 0;
802 
803     while(iter->id && iter->id != cmd->cmdID)
804         iter++;
805 
806     if(!iter->id || !iter->query)
807         return OLECMDERR_E_NOTSUPPORTED;
808 
809     return iter->query(This, cmd);
810 }
811 
OleCommandTarget_QueryStatus(IOleCommandTarget * iface,const GUID * pguidCmdGroup,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT * pCmdText)812 static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
813         ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
814 {
815     HTMLDocument *This = impl_from_IOleCommandTarget(iface);
816     HRESULT hres;
817 
818     TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
819 
820     if(pCmdText)
821         FIXME("Unsupported pCmdText\n");
822     if(!cCmds)
823         return S_OK;
824 
825     if(!pguidCmdGroup) {
826         ULONG i;
827 
828         for(i=0; i<cCmds; i++) {
829             if(prgCmds[i].cmdID < OLECMDID_OPEN || prgCmds[i].cmdID >= sizeof(exec_table)/sizeof(*exec_table)) {
830                 WARN("Unsupported cmdID = %d\n", prgCmds[i].cmdID);
831                 prgCmds[i].cmdf = 0;
832             }else {
833                 if(prgCmds[i].cmdID == OLECMDID_OPEN || prgCmds[i].cmdID == OLECMDID_NEW) {
834                     IOleCommandTarget *cmdtrg = NULL;
835                     OLECMD olecmd;
836 
837                     prgCmds[i].cmdf = OLECMDF_SUPPORTED;
838                     if(This->doc_obj->client) {
839                         hres = IOleClientSite_QueryInterface(This->doc_obj->client, &IID_IOleCommandTarget,
840                                 (void**)&cmdtrg);
841                         if(SUCCEEDED(hres)) {
842                             olecmd.cmdID = prgCmds[i].cmdID;
843                             olecmd.cmdf = 0;
844 
845                             hres = IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &olecmd, NULL);
846                             if(SUCCEEDED(hres) && olecmd.cmdf)
847                                 prgCmds[i].cmdf = olecmd.cmdf;
848                         }
849                     }else {
850                         ERR("This->client == NULL, native would crash\n");
851                     }
852                 }else {
853                     prgCmds[i].cmdf = exec_table[prgCmds[i].cmdID].cmdf;
854                     TRACE("cmdID = %d  returning %x\n", prgCmds[i].cmdID, prgCmds[i].cmdf);
855                 }
856             }
857         }
858 
859         return (prgCmds[cCmds-1].cmdf & OLECMDF_SUPPORTED) ? S_OK : OLECMDERR_E_NOTSUPPORTED;
860     }
861 
862     if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
863         ULONG i;
864 
865         for(i=0; i<cCmds; i++) {
866             hres = query_from_table(This, base_cmds, prgCmds+i);
867             if(hres == OLECMDERR_E_NOTSUPPORTED)
868                 hres = query_from_table(This, editmode_cmds, prgCmds+i);
869             if(hres == OLECMDERR_E_NOTSUPPORTED)
870                 FIXME("CGID_MSHTML: unsupported cmdID %d\n", prgCmds[i].cmdID);
871         }
872 
873         return (prgCmds[cCmds-1].cmdf & OLECMDF_SUPPORTED) ? S_OK : OLECMDERR_E_NOTSUPPORTED;
874     }
875 
876     FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
877     return OLECMDERR_E_UNKNOWNGROUP;
878 }
879 
exec_from_table(HTMLDocument * This,const cmdtable_t * cmdtable,DWORD cmdid,DWORD cmdexecopt,VARIANT * in,VARIANT * out)880 static HRESULT exec_from_table(HTMLDocument *This, const cmdtable_t *cmdtable, DWORD cmdid,
881                                DWORD cmdexecopt, VARIANT *in, VARIANT *out)
882 {
883     const cmdtable_t *iter = cmdtable;
884 
885     while(iter->id && iter->id != cmdid)
886         iter++;
887 
888     if(!iter->id || !iter->exec)
889         return OLECMDERR_E_NOTSUPPORTED;
890 
891     return iter->exec(This, cmdexecopt, in, out);
892 }
893 
OleCommandTarget_Exec(IOleCommandTarget * iface,const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)894 static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
895         DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
896 {
897     HTMLDocument *This = impl_from_IOleCommandTarget(iface);
898 
899     if(!pguidCmdGroup) {
900         if(nCmdID < OLECMDID_OPEN || nCmdID >= sizeof(exec_table)/sizeof(*exec_table) || !exec_table[nCmdID].func) {
901             WARN("Unsupported cmdID = %d\n", nCmdID);
902             return OLECMDERR_E_NOTSUPPORTED;
903         }
904 
905         return exec_table[nCmdID].func(This, nCmdexecopt, pvaIn, pvaOut);
906     }else if(IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) {
907         FIXME("unsupported nCmdID %d of CGID_Explorer group\n", nCmdID);
908         TRACE("%p %p\n", pvaIn, pvaOut);
909         return OLECMDERR_E_NOTSUPPORTED;
910     }else if(IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup)) {
911         FIXME("unsupported nCmdID %d of CGID_ShellDocView group\n", nCmdID);
912         return OLECMDERR_E_NOTSUPPORTED;
913     }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
914         HRESULT hres = exec_from_table(This, base_cmds, nCmdID, nCmdexecopt, pvaIn, pvaOut);
915         if(hres == OLECMDERR_E_NOTSUPPORTED)
916             hres = exec_from_table(This, editmode_cmds, nCmdID,
917                                    nCmdexecopt, pvaIn, pvaOut);
918         if(hres == OLECMDERR_E_NOTSUPPORTED)
919             FIXME("unsupported nCmdID %d of CGID_MSHTML group\n", nCmdID);
920 
921         return hres;
922     }
923 
924     FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
925     return OLECMDERR_E_UNKNOWNGROUP;
926 }
927 
928 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
929     OleCommandTarget_QueryInterface,
930     OleCommandTarget_AddRef,
931     OleCommandTarget_Release,
932     OleCommandTarget_QueryStatus,
933     OleCommandTarget_Exec
934 };
935 
show_context_menu(HTMLDocumentObj * This,DWORD dwID,POINT * ppt,IDispatch * elem)936 void show_context_menu(HTMLDocumentObj *This, DWORD dwID, POINT *ppt, IDispatch *elem)
937 {
938     HMENU menu_res, menu;
939     DWORD cmdid;
940 
941     if(This->hostui && S_OK == IDocHostUIHandler_ShowContextMenu(This->hostui,
942             dwID, ppt, (IUnknown*)&This->basedoc.IOleCommandTarget_iface, elem))
943         return;
944 
945     menu_res = LoadMenuW(get_shdoclc(), MAKEINTRESOURCEW(IDR_BROWSE_CONTEXT_MENU));
946     menu = GetSubMenu(menu_res, dwID);
947 
948     cmdid = TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
949             ppt->x, ppt->y, 0, This->hwnd, NULL);
950     DestroyMenu(menu_res);
951 
952     if(cmdid)
953         IOleCommandTarget_Exec(&This->basedoc.IOleCommandTarget_iface, &CGID_MSHTML, cmdid, 0,
954                 NULL, NULL);
955 }
956 
HTMLDocument_OleCmd_Init(HTMLDocument * This)957 void HTMLDocument_OleCmd_Init(HTMLDocument *This)
958 {
959     This->IOleCommandTarget_iface.lpVtbl = &OleCommandTargetVtbl;
960 }
961