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