rsaenh: Win64 printf format warning fixes.
[wine] / dlls / mshtml / olecmd.c
1 /*
2  * Copyright 2005-2006 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 "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "ole2.h"
31 #include "shlguid.h"
32 #include "mshtmdid.h"
33 #include "idispids.h"
34 #include "mshtmcid.h"
35
36 #include "wine/debug.h"
37
38 #include "mshtml_private.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
41
42 /**********************************************************
43  * IOleCommandTarget implementation
44  */
45
46 #define CMDTARGET_THIS(iface) DEFINE_THIS(HTMLDocument, OleCommandTarget, iface)
47
48 static HRESULT exec_open(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
49 {
50     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
51     return E_NOTIMPL;
52 }
53
54 static HRESULT exec_new(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
55 {
56     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
57     return E_NOTIMPL;
58 }
59
60 static HRESULT exec_save(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
61 {
62     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
63     return E_NOTIMPL;
64 }
65
66 static HRESULT exec_save_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
67 {
68     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
69     return E_NOTIMPL;
70 }
71
72 static HRESULT exec_save_copy_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
73 {
74     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
75     return E_NOTIMPL;
76 }
77
78 static HRESULT exec_print(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
84 static HRESULT exec_print_preview(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
90 static HRESULT exec_page_setup(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
96 static HRESULT exec_spell(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
102 static HRESULT exec_properties(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
108 static HRESULT exec_cut(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
109 {
110     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
111     return E_NOTIMPL;
112 }
113
114 static HRESULT exec_copy(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
115 {
116     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
117     return E_NOTIMPL;
118 }
119
120 static HRESULT exec_paste(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
121 {
122     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
123     return E_NOTIMPL;
124 }
125
126 static HRESULT exec_paste_special(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
127 {
128     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
129     return E_NOTIMPL;
130 }
131
132 static HRESULT exec_undo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
133 {
134     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
135     return E_NOTIMPL;
136 }
137
138 static HRESULT exec_rendo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
139 {
140     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
141     return E_NOTIMPL;
142 }
143
144 static HRESULT exec_select_all(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
145 {
146     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
147     return E_NOTIMPL;
148 }
149
150 static HRESULT exec_clear_selection(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
151 {
152     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
153     return E_NOTIMPL;
154 }
155
156 static HRESULT exec_zoom(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
157 {
158     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
159     return E_NOTIMPL;
160 }
161
162 static HRESULT exec_get_zoom_range(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
163 {
164     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
165     return E_NOTIMPL;
166 }
167
168 static HRESULT exec_refresh(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
169 {
170     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
171     return E_NOTIMPL;
172 }
173
174 static HRESULT exec_stop(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
175 {
176     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
177     return E_NOTIMPL;
178 }
179
180 static HRESULT exec_stop_download(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
181 {
182     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
183     return E_NOTIMPL;
184 }
185
186 static HRESULT exec_delete(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
187 {
188     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
189     return E_NOTIMPL;
190 }
191
192 static HRESULT exec_enable_interaction(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
193 {
194     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
195     return E_NOTIMPL;
196 }
197
198 static HRESULT exec_on_unload(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
199 {
200     TRACE("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
201
202     /* Tests show that we have nothing more to do here */
203
204     if(pvaOut) {
205         V_VT(pvaOut) = VT_BOOL;
206         V_BOOL(pvaOut) = VARIANT_TRUE;
207     }
208
209     return S_OK;
210 }
211
212 static HRESULT exec_show_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
213 {
214     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
215     return E_NOTIMPL;
216 }
217
218 static HRESULT exec_show_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
219 {
220     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
221     return E_NOTIMPL;
222 }
223
224 static HRESULT exec_close(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
225 {
226     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
227     return E_NOTIMPL;
228 }
229
230 static HRESULT exec_set_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
231 {
232     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
233     return E_NOTIMPL;
234 }
235
236 static HRESULT exec_get_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
237 {
238     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
239     return E_NOTIMPL;
240 }
241
242 static void do_ns_command(NSContainer *This, const char *cmd, nsICommandParams *nsparam)
243 {
244     nsICommandManager *cmdmgr;
245     nsIInterfaceRequestor *iface_req;
246     nsresult nsres;
247
248     FIXME("(%p)\n", This);
249
250     nsres = nsIWebBrowser_QueryInterface(This->webbrowser,
251             &IID_nsIInterfaceRequestor, (void**)&iface_req);
252     if(NS_FAILED(nsres)) {
253         ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres);
254         return;
255     }
256
257     nsres = nsIInterfaceRequestor_GetInterface(iface_req, &IID_nsICommandManager,
258                                                (void**)&cmdmgr);
259     nsIInterfaceRequestor_Release(iface_req);
260     if(NS_FAILED(nsres)) {
261         ERR("Could not get nsICommandManager: %08x\n", nsres);
262         return;
263     }
264
265     nsres = nsICommandManager_DoCommand(cmdmgr, cmd, nsparam, NULL);
266     if(NS_FAILED(nsres))
267         ERR("DoCommand(%s) failed: %08x\n", debugstr_a(cmd), nsres);
268
269     nsICommandManager_Release(cmdmgr);
270 }
271
272 static nsresult get_ns_command_state(NSContainer *This, const char *cmd, nsICommandParams *nsparam)
273 {
274     nsICommandManager *cmdmgr;
275     nsIInterfaceRequestor *iface_req;
276     nsresult nsres;
277
278     nsres = nsIWebBrowser_QueryInterface(This->webbrowser,
279             &IID_nsIInterfaceRequestor, (void**)&iface_req);
280     if(NS_FAILED(nsres)) {
281         ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres);
282         return nsres;
283     }
284
285     nsres = nsIInterfaceRequestor_GetInterface(iface_req, &IID_nsICommandManager,
286                                                (void**)&cmdmgr);
287     nsIInterfaceRequestor_Release(iface_req);
288     if(NS_FAILED(nsres)) {
289         ERR("Could not get nsICommandManager: %08x\n", nsres);
290         return nsres;
291     }
292
293     nsres = nsICommandManager_GetCommandState(cmdmgr, cmd, NULL, nsparam);
294     if(NS_FAILED(nsres))
295         ERR("GetCommandState(%s) failed: %08x\n", debugstr_a(cmd), nsres);
296
297     nsICommandManager_Release(cmdmgr);
298     return nsres;
299 }
300
301 static HRESULT exec_fontname(HTMLDocument *This, VARIANT *in, VARIANT *out)
302 {
303     TRACE("(%p)->(%p %p)\n", This, in, out);
304
305     if(!This->nscontainer)
306         return E_FAIL;
307
308     if(in) {
309         nsICommandParams *nsparam = create_nscommand_params();
310         char *stra;
311         DWORD len;
312
313         if(V_VT(in) != VT_BSTR) {
314             FIXME("Unsupported vt=%d\n", V_VT(out));
315             return E_INVALIDARG;
316         }
317
318         len = WideCharToMultiByte(CP_ACP, 0, V_BSTR(in), -1, NULL, 0, NULL, NULL);
319         stra = mshtml_alloc(len);
320         WideCharToMultiByte(CP_ACP, 0, V_BSTR(in), -1, stra, -1, NULL, NULL);
321         nsICommandParams_SetCStringValue(nsparam, "state_attribute", stra);
322         mshtml_free(stra);
323
324         do_ns_command(This->nscontainer, "cmd_fontFace", nsparam);
325
326         nsICommandParams_Release(nsparam);
327     }
328
329     if(out) {
330         nsICommandParams *nsparam;
331         LPWSTR strw;
332         char *stra;
333         DWORD len;
334         nsresult nsres;
335
336         if(V_VT(out) != VT_BSTR) {
337             FIXME("Unsupported vt=%d\n", V_VT(out));
338             return E_INVALIDARG;
339         }
340
341         nsparam = create_nscommand_params();
342
343         nsres = get_ns_command_state(This->nscontainer, "cmd_fontFace", nsparam);
344         if(NS_FAILED(nsres))
345             return S_OK;
346
347         nsICommandParams_GetCStringValue(nsparam, "state_attribute", &stra);
348         nsICommandParams_Release(nsparam);
349
350         len = MultiByteToWideChar(CP_ACP, 0, stra, -1, NULL, 0);
351         strw = mshtml_alloc(len*sizeof(WCHAR));
352         MultiByteToWideChar(CP_ACP, 0, stra, -1, strw, -1);
353         nsfree(stra);
354
355         V_BSTR(out) = SysAllocString(strw);
356         mshtml_free(strw);
357     }
358
359     return S_OK;
360 }
361
362 static HRESULT exec_bold(HTMLDocument *This)
363 {
364     TRACE("(%p)\n", This);
365
366     if(This->nscontainer)
367         do_ns_command(This->nscontainer, "cmd_bold", NULL);
368
369     return S_OK;
370 }
371
372 static HRESULT exec_italic(HTMLDocument *This)
373 {
374     TRACE("(%p)\n", This);
375
376     if(This->nscontainer)
377         do_ns_command(This->nscontainer, "cmd_italic", NULL);
378
379     return S_OK;
380 }
381
382 static HRESULT exec_underline(HTMLDocument *This)
383 {
384     TRACE("(%p)\n", This);
385
386     if(This->nscontainer)
387         do_ns_command(This->nscontainer, "cmd_underline", NULL);
388
389     return S_OK;
390 }
391
392 static HRESULT exec_browsemode(HTMLDocument *This)
393 {
394     WARN("(%p)\n", This);
395
396     This->usermode = BROWSEMODE;
397
398     return S_OK;
399 }
400
401 static void setup_ns_editing(NSContainer *This)
402 {
403     nsIInterfaceRequestor *iface_req;
404     nsIEditingSession *editing_session = NULL;
405     nsIURIContentListener *listener = NULL;
406     nsIDOMWindow *dom_window = NULL;
407     nsresult nsres;
408
409     nsres = nsIWebBrowser_QueryInterface(This->webbrowser,
410             &IID_nsIInterfaceRequestor, (void**)&iface_req);
411     if(NS_FAILED(nsres)) {
412         ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres);
413         return;
414     }
415
416     nsres = nsIInterfaceRequestor_GetInterface(iface_req, &IID_nsIEditingSession,
417                                                (void**)&editing_session);
418     nsIInterfaceRequestor_Release(iface_req);
419     if(NS_FAILED(nsres)) {
420         ERR("Could not get nsIEditingSession: %08x\n", nsres);
421         return;
422     }
423
424     nsres = nsIWebBrowser_GetContentDOMWindow(This->webbrowser, &dom_window);
425     nsIDOMWindow_Release(dom_window);
426     if(NS_FAILED(nsres)) {
427         ERR("Could not get content DOM window: %08x\n", nsres);
428         nsIEditingSession_Release(editing_session);
429         return;
430     }
431
432     nsres = nsIEditingSession_MakeWindowEditable(editing_session, dom_window, NULL, FALSE);
433     nsIEditingSession_Release(editing_session);
434     if(NS_FAILED(nsres)) {
435         ERR("MakeWindowEditable failed: %08x\n", nsres);
436         return;
437     }
438
439     /* MakeWindowEditable changes WebBrowser's parent URI content listener.
440      * It seams to be a bug in Gecko. To workaround it we set our content
441      * listener again and Gecko's one as its parent.
442      */
443     nsIWebBrowser_GetParentURIContentListener(This->webbrowser, &listener);
444     nsIURIContentListener_SetParentContentListener(NSURICL(This), listener);
445     nsIURIContentListener_Release(listener);
446     nsIWebBrowser_SetParentURIContentListener(This->webbrowser, NSURICL(This));
447 }
448
449 static HRESULT exec_editmode(HTMLDocument *This)
450 {
451     HRESULT hres;
452
453     TRACE("(%p)\n", This);
454
455     This->usermode = EDITMODE;
456
457     if(This->frame)
458         IOleInPlaceFrame_SetStatusText(This->frame, NULL);
459
460     if(This->client) {
461         IOleCommandTarget *cmdtrg = NULL;
462
463         hres = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget,
464                 (void**)&cmdtrg);
465         if(SUCCEEDED(hres)) {
466             VARIANT var;
467
468             V_VT(&var) = VT_I4;
469             V_I4(&var) = 0;
470             IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL);
471         }
472     }
473
474     if(This->hostui) {
475         DOCHOSTUIINFO hostinfo;
476
477         memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
478         hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
479         hres = IDocHostUIHandler_GetHostInfo(This->hostui, &hostinfo);
480         if(SUCCEEDED(hres))
481             /* FIXME: use hostinfo */
482             TRACE("hostinfo = {%u %08x %08x %s %s}\n",
483                     hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
484                     debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
485     }
486
487     if(This->client) {
488         VARIANT silent, offline;
489
490         hres = get_client_disp_property(This->client, DISPID_AMBIENT_SILENT, &silent);
491         if(SUCCEEDED(hres)) {
492             if(V_VT(&silent) != VT_BOOL)
493                 WARN("V_VT(silent) = %d\n", V_VT(&silent));
494             else if(V_BOOL(&silent))
495                 FIXME("silent == true\n");
496         }
497
498         hres = get_client_disp_property(This->client,
499                 DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &offline); 
500         if(SUCCEEDED(hres)) {
501             if(V_VT(&silent) != VT_BOOL)
502                 WARN("V_VT(offline) = %d\n", V_VT(&silent));
503             else if(V_BOOL(&silent))
504                 FIXME("offline == true\n");
505         }
506     }
507
508     if(This->nscontainer)
509         setup_ns_editing(This->nscontainer);
510
511     /* 
512      * FIXME: We should load about:protocol here.
513      */
514     This->readystate = READYSTATE_LOADING;
515     call_property_onchanged(This->cp_propnotif, DISPID_READYSTATE);
516
517     return S_OK;
518 }
519
520 static HRESULT exec_baselinefont3(HTMLDocument *This)
521 {
522     FIXME("(%p)\n", This);
523     return S_OK;
524 }
525
526 static const struct {
527     OLECMDF cmdf;
528     HRESULT (*func)(HTMLDocument*,DWORD,VARIANT*,VARIANT*);
529 } exec_table[OLECMDID_GETPRINTTEMPLATE+1] = {
530     {0},
531     { OLECMDF_SUPPORTED,                  exec_open                 }, /* OLECMDID_OPEN */
532     { OLECMDF_SUPPORTED,                  exec_new                  }, /* OLECMDID_NEW */
533     { OLECMDF_SUPPORTED,                  exec_save                 }, /* OLECMDID_SAVE */
534     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_save_as              }, /* OLECMDID_SAVEAS */
535     { OLECMDF_SUPPORTED,                  exec_save_copy_as         }, /* OLECMDID_SAVECOPYAS */
536     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_print                }, /* OLECMDID_PRINT */
537     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_print_preview        }, /* OLECMDID_PRINTPREVIEW */
538     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_page_setup           }, /* OLECMDID_PAGESETUP */
539     { OLECMDF_SUPPORTED,                  exec_spell                }, /* OLECMDID_SPELL */
540     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_properties           }, /* OLECMDID_PROPERTIES */
541     { OLECMDF_SUPPORTED,                  exec_cut                  }, /* OLECMDID_CUT */
542     { OLECMDF_SUPPORTED,                  exec_copy                 }, /* OLECMDID_COPY */
543     { OLECMDF_SUPPORTED,                  exec_paste                }, /* OLECMDID_PASTE */
544     { OLECMDF_SUPPORTED,                  exec_paste_special        }, /* OLECMDID_PASTESPECIAL */
545     { OLECMDF_SUPPORTED,                  exec_undo                 }, /* OLECMDID_UNDO */
546     { OLECMDF_SUPPORTED,                  exec_rendo                }, /* OLECMDID_REDO */
547     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_select_all           }, /* OLECMDID_SELECTALL */
548     { OLECMDF_SUPPORTED,                  exec_clear_selection      }, /* OLECMDID_CLEARSELECTION */
549     { OLECMDF_SUPPORTED,                  exec_zoom                 }, /* OLECMDID_ZOOM */
550     { OLECMDF_SUPPORTED,                  exec_get_zoom_range       }, /* OLECMDID_GETZOOMRANGE */
551     {0},
552     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_refresh              }, /* OLECMDID_REFRESH */
553     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_stop                 }, /* OLECMDID_STOP */
554     {0},{0},{0},{0},{0},{0},
555     { OLECMDF_SUPPORTED,                  exec_stop_download        }, /* OLECMDID_STOPDOWNLOAD */
556     {0},{0},
557     { OLECMDF_SUPPORTED,                  exec_delete               }, /* OLECMDID_DELETE */
558     {0},{0},
559     { OLECMDF_SUPPORTED,                  exec_enable_interaction   }, /* OLECMDID_ENABLE_INTERACTION */
560     { OLECMDF_SUPPORTED,                  exec_on_unload            }, /* OLECMDID_ONUNLOAD */
561     {0},{0},{0},{0},{0},
562     { OLECMDF_SUPPORTED,                  exec_show_page_setup      }, /* OLECMDID_SHOWPAGESETUP */
563     { OLECMDF_SUPPORTED,                  exec_show_print           }, /* OLECMDID_SHOWPRINT */
564     {0},{0},
565     { OLECMDF_SUPPORTED,                  exec_close                }, /* OLECMDID_CLOSE */
566     {0},{0},{0},
567     { OLECMDF_SUPPORTED,                  exec_set_print_template   }, /* OLECMDID_SETPRINTTEMPLATE */
568     { OLECMDF_SUPPORTED,                  exec_get_print_template   }  /* OLECMDID_GETPRINTTEMPLATE */
569 };
570
571 static HRESULT WINAPI OleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
572 {
573     HTMLDocument *This = CMDTARGET_THIS(iface);
574     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
575 }
576
577 static ULONG WINAPI OleCommandTarget_AddRef(IOleCommandTarget *iface)
578 {
579     HTMLDocument *This = CMDTARGET_THIS(iface);
580     return IHTMLDocument2_AddRef(HTMLDOC(This));
581 }
582
583 static ULONG WINAPI OleCommandTarget_Release(IOleCommandTarget *iface)
584 {
585     HTMLDocument *This = CMDTARGET_THIS(iface);
586     return IHTMLDocument_Release(HTMLDOC(This));
587 }
588
589 static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
590         ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
591 {
592     HTMLDocument *This = CMDTARGET_THIS(iface);
593     HRESULT hres = S_OK, hr;
594
595     TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
596
597     if(!pguidCmdGroup) {
598         ULONG i;
599
600         for(i=0; i<cCmds; i++) {
601             if(prgCmds[i].cmdID<OLECMDID_OPEN || prgCmds[i].cmdID>OLECMDID_GETPRINTTEMPLATE) {
602                 WARN("Unsupported cmdID = %d\n", prgCmds[i].cmdID);
603                 prgCmds[i].cmdf = 0;
604                 hres = OLECMDERR_E_NOTSUPPORTED;
605             }else {
606                 if(prgCmds[i].cmdID == OLECMDID_OPEN || prgCmds[i].cmdID == OLECMDID_NEW) {
607                     IOleCommandTarget *cmdtrg = NULL;
608                     OLECMD olecmd;
609
610                     prgCmds[i].cmdf = OLECMDF_SUPPORTED;
611                     if(This->client) {
612                         hr = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget,
613                                 (void**)&cmdtrg);
614                         if(SUCCEEDED(hr)) {
615                             olecmd.cmdID = prgCmds[i].cmdID;
616                             olecmd.cmdf = 0;
617
618                             hr = IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &olecmd, NULL);
619                             if(SUCCEEDED(hr) && olecmd.cmdf)
620                                 prgCmds[i].cmdf = olecmd.cmdf;
621                         }
622                     }else {
623                         ERR("This->client == NULL, native would crash\n");
624                     }
625                 }else {
626                     prgCmds[i].cmdf = exec_table[prgCmds[i].cmdID].cmdf;
627                     TRACE("cmdID = %d  returning %x\n", prgCmds[i].cmdID, prgCmds[i].cmdf);
628                 }
629                 hres = S_OK;
630             }
631         }
632
633         if(pCmdText)
634             FIXME("Set pCmdText\n");
635     }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
636         ULONG i;
637
638         for(i=0; i<cCmds; i++) {
639             switch(prgCmds[i].cmdID) {
640             case IDM_COPY:
641                 FIXME("CGID_MSHTML: IDM_COPY\n");
642                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
643                 break;
644             case IDM_CUT:
645                 FIXME("CGID_MSHTML: IDM_CUT\n");
646                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
647                 break;
648             case IDM_FONTNAME:
649                 FIXME("CGID_MSHTML: IDM_FONTNAME\n");
650                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
651                 break;
652             case IDM_FONTSIZE:
653                 FIXME("CGID_MSHTML: IDM_FONTSIZE\n");
654                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
655                 break;
656             case IDM_PASTE:
657                 FIXME("CGID_MSHTML: IDM_PASTE\n");
658                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
659                 break;
660             case IDM_BOLD:
661                 FIXME("CGID_MSHTML: IDM_BOLD\n");
662                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
663                 break;
664             case IDM_FORECOLOR:
665                 FIXME("CGID_MSHTML: IDM_FORECOLOR\n");
666                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
667                 break;
668             case IDM_ITALIC:
669                 FIXME("CGID_MSHTML: IDM_ITALIC\n");
670                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
671                 break;
672             case IDM_JUSTIFYCENTER:
673                 FIXME("CGID_MSHTML: IDM_JUSTIFYCENTER\n");
674                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
675                 break;
676             case IDM_JUSTIFYLEFT:
677                 FIXME("CGID_MSHTML: IDM_JUSTIFYLEFT\n");
678                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
679                 break;
680             case IDM_JUSTIFYRIGHT:
681                 FIXME("CGID_MSHTML: IDM_JUSTIFYRIGHT\n");
682                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
683                 break;
684             case IDM_UNDERLINE:
685                 FIXME("CGID_MSHTML: IDM_UNDERLINE\n");
686                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
687                 break;
688             case IDM_HORIZONTALLINE:
689                 FIXME("CGID_MSHTML: IDM_HORIZONTALLINE\n");
690                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
691                 break;
692             case IDM_ORDERLIST:
693                 FIXME("CGID_MSHTML: IDM_ORDERLIST\n");
694                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
695                 break;
696             case IDM_UNORDERLIST:
697                 FIXME("CGID_MSHTML: IDM_UNORDERLIST\n");
698                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
699                 break;
700             case IDM_INDENT:
701                 FIXME("CGID_MSHTML: IDM_INDENT\n");
702                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
703                 break;
704             case IDM_OUTDENT:
705                 FIXME("CGID_MSHTML: IDM_OUTDENT\n");
706                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
707                 break;
708             case IDM_BLOCKDIRLTR:
709                 FIXME("CGID_MSHTML: IDM_BLOCKDIRLTR\n");
710                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
711                 break;
712             case IDM_BLOCKDIRRTL:
713                 FIXME("CGID_MSHTML: IDM_BLOCKDIRRTL\n");
714                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
715                 break;
716             default:
717                 FIXME("CGID_MSHTML: unsupported cmdID %d\n", prgCmds[i].cmdID);
718                 prgCmds[i].cmdf = 0;
719             }
720         }
721
722         hres = prgCmds[i-1].cmdf ? S_OK : OLECMDERR_E_NOTSUPPORTED;
723
724         if(pCmdText)
725             FIXME("Set pCmdText\n");
726     }else {
727         FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
728         hres = OLECMDERR_E_UNKNOWNGROUP;
729     }
730
731     return hres;
732 }
733
734 static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
735         DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
736 {
737     HTMLDocument *This = CMDTARGET_THIS(iface);
738
739     if(!pguidCmdGroup) {
740         if(nCmdID<OLECMDID_OPEN || nCmdID>OLECMDID_GETPRINTTEMPLATE || !exec_table[nCmdID].func) {
741             WARN("Unsupported cmdID = %d\n", nCmdID);
742             return OLECMDERR_E_NOTSUPPORTED;
743         }
744
745         return exec_table[nCmdID].func(This, nCmdexecopt, pvaIn, pvaOut);
746     }else if(IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) {
747         FIXME("unsupported nCmdID %d of CGID_Explorer group\n", nCmdID);
748         TRACE("%p %p\n", pvaIn, pvaOut);
749         return OLECMDERR_E_NOTSUPPORTED;
750     }else if(IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup)) {
751         FIXME("unsupported nCmdID %d of CGID_ShellDocView group\n", nCmdID);
752         return OLECMDERR_E_NOTSUPPORTED;
753     }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
754         switch(nCmdID) {
755         case IDM_FONTNAME:
756             return exec_fontname(This, pvaIn, pvaOut);
757         case IDM_BOLD:
758             if(pvaIn || pvaOut)
759                 FIXME("unsupported arguments\n");
760             return exec_bold(This);
761         case IDM_ITALIC:
762             if(pvaIn || pvaOut)
763                 FIXME("unsupported arguments\n");
764             return exec_italic(This);
765         case IDM_UNDERLINE:
766             if(pvaIn || pvaOut)
767                 FIXME("unsupported arguments\n");
768             return exec_underline(This);
769         case IDM_BROWSEMODE:
770             if(pvaIn || pvaOut)
771                 FIXME("unsupported arguments\n");
772             return exec_browsemode(This);
773         case IDM_EDITMODE:
774             if(pvaIn || pvaOut)
775                 FIXME("unsupported arguments\n");
776             return exec_editmode(This);
777         case IDM_BASELINEFONT3:
778             return exec_baselinefont3(This);
779         default:
780             FIXME("unsupported nCmdID %d of CGID_MSHTML group\n", nCmdID);
781             return OLECMDERR_E_NOTSUPPORTED;
782         }
783     }
784
785     FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
786     return OLECMDERR_E_UNKNOWNGROUP;
787 }
788
789 #undef CMDTARGET_THIS
790
791 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
792     OleCommandTarget_QueryInterface,
793     OleCommandTarget_AddRef,
794     OleCommandTarget_Release,
795     OleCommandTarget_QueryStatus,
796     OleCommandTarget_Exec
797 };
798
799 void HTMLDocument_OleCmd_Init(HTMLDocument *This)
800 {
801     This->lpOleCommandTargetVtbl = &OleCommandTargetVtbl;
802 }