ntdll: Fix compilation on systems that don't support nameless unions.
[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 #include "wine/unicode.h"
38
39 #include "mshtml_private.h"
40 #include "resource.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
43
44 #define NSCMD_BOLD "cmd_bold"
45 #define NSCMD_ITALIC "cmd_italic"
46 #define NSCMD_UNDERLINE "cmd_underline"
47 #define NSCMD_FONTCOLOR "cmd_fontColor"
48 #define NSCMD_ALIGN "cmd_align"
49 #define NSCMD_FONTFACE "cmd_fontFace"
50 #define NSCMD_INDENT "cmd_indent"
51 #define NSCMD_OUTDENT "cmd_outdent"
52 #define NSCMD_INSERTHR "cmd_insertHR"
53 #define NSCMD_UL "cmd_ul"
54 #define NSCMD_OL "cmd_ol"
55
56 #define NSSTATE_ATTRIBUTE "state_attribute"
57 #define NSSTATE_ALL "state_all"
58
59 #define NSALIGN_CENTER "center"
60 #define NSALIGN_LEFT   "left"
61 #define NSALIGN_RIGHT  "right"
62
63 /**********************************************************
64  * IOleCommandTarget implementation
65  */
66
67 #define CMDTARGET_THIS(iface) DEFINE_THIS(HTMLDocument, OleCommandTarget, iface)
68
69 static HRESULT exec_open(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
70 {
71     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
72     return E_NOTIMPL;
73 }
74
75 static HRESULT exec_new(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
76 {
77     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
78     return E_NOTIMPL;
79 }
80
81 static HRESULT exec_save(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
82 {
83     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
84     return E_NOTIMPL;
85 }
86
87 static HRESULT exec_save_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
88 {
89     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
90     return E_NOTIMPL;
91 }
92
93 static HRESULT exec_save_copy_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
94 {
95     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
96     return E_NOTIMPL;
97 }
98
99 static nsresult set_head_text(nsIPrintSettings *settings, LPCWSTR template, BOOL head, int pos)
100 {
101     if(head) {
102         switch(pos) {
103         case 0:
104             return nsIPrintSettings_SetHeaderStrLeft(settings, template);
105         case 1:
106             return nsIPrintSettings_SetHeaderStrRight(settings, template);
107         case 2:
108             return nsIPrintSettings_SetHeaderStrCenter(settings, template);
109         }
110     }else {
111         switch(pos) {
112         case 0:
113             return nsIPrintSettings_SetFooterStrLeft(settings, template);
114         case 1:
115             return nsIPrintSettings_SetFooterStrRight(settings, template);
116         case 2:
117             return nsIPrintSettings_SetFooterStrCenter(settings, template);
118         }
119     }
120
121     return NS_OK;
122 }
123
124 static void set_print_template(nsIPrintSettings *settings, LPCWSTR template, BOOL head)
125 {
126     PRUnichar nstemplate[200]; /* FIXME: Use dynamic allocation */
127     PRUnichar *p = nstemplate;
128     LPCWSTR ptr=template;
129     int pos=0;
130
131     while(*ptr) {
132         if(*ptr != '&') {
133             *p++ = *ptr++;
134             continue;
135         }
136
137         switch(*++ptr) {
138         case '&':
139             *p++ = '&';
140             *p++ = '&';
141             ptr++;
142             break;
143         case 'b': /* change align */
144             ptr++;
145             *p = 0;
146             set_head_text(settings, nstemplate, head, pos);
147             p = nstemplate;
148             pos++;
149             break;
150         case 'd': { /* short date */
151             SYSTEMTIME systime;
152             GetLocalTime(&systime);
153             GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &systime, NULL, p,
154                     sizeof(nstemplate)-(p-nstemplate)*sizeof(WCHAR));
155             p += strlenW(p);
156             ptr++;
157             break;
158         }
159         case 'p': /* page number */
160             *p++ = '&';
161             *p++ = 'P';
162             ptr++;
163             break;
164         case 'P': /* page count */
165             *p++ = '?'; /* FIXME */
166             ptr++;
167             break;
168         case 'u':
169             *p++ = '&';
170             *p++ = 'U';
171             ptr++;
172             break;
173         case 'w':
174             /* FIXME: set window title */
175             ptr++;
176             break;
177         default:
178             *p++ = '&';
179             *p++ = *ptr++;
180         }
181     }
182
183     *p = 0;
184     set_head_text(settings, nstemplate, head, pos);
185
186     while(++pos < 3)
187         set_head_text(settings, p, head, pos);
188 }
189
190 static void set_default_templates(nsIPrintSettings *settings)
191 {
192     WCHAR buf[64];
193
194     static const PRUnichar empty[] = {0};
195
196     nsIPrintSettings_SetHeaderStrLeft(settings, empty);
197     nsIPrintSettings_SetHeaderStrRight(settings, empty);
198     nsIPrintSettings_SetHeaderStrCenter(settings, empty);
199     nsIPrintSettings_SetFooterStrLeft(settings, empty);
200     nsIPrintSettings_SetFooterStrRight(settings, empty);
201     nsIPrintSettings_SetFooterStrCenter(settings, empty);
202
203     if(LoadStringW(get_shdoclc(), IDS_PRINT_HEADER_TEMPLATE, buf,
204                    sizeof(buf)/sizeof(WCHAR)))
205         set_print_template(settings, buf, TRUE);
206
207
208     if(LoadStringW(get_shdoclc(), IDS_PRINT_FOOTER_TEMPLATE, buf,
209                    sizeof(buf)/sizeof(WCHAR)))
210         set_print_template(settings, buf, FALSE);
211
212 }
213
214 static HRESULT exec_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
215 {
216     nsIInterfaceRequestor *iface_req;
217     nsIWebBrowserPrint *nsprint;
218     nsIPrintSettings *settings;
219     nsresult nsres;
220
221     TRACE("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
222
223     if(pvaOut)
224         FIXME("unsupported pvaOut\n");
225
226     if(!This->nscontainer)
227         return S_OK;
228
229     nsres = nsIWebBrowser_QueryInterface(This->nscontainer->webbrowser,
230             &IID_nsIInterfaceRequestor, (void**)&iface_req);
231     if(NS_FAILED(nsres)) {
232         ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres);
233         return S_OK;
234     }
235
236     nsres = nsIInterfaceRequestor_GetInterface(iface_req, &IID_nsIWebBrowserPrint,
237             (void**)&nsprint);
238     nsIInterfaceRequestor_Release(iface_req);
239     if(NS_FAILED(nsres)) {
240         ERR("Could not get nsIWebBrowserPrint: %08x\n", nsres);
241         return S_OK;
242     }
243
244     nsres = nsIWebBrowserPrint_GetGlobalPrintSettings(nsprint, &settings);
245     if(NS_FAILED(nsres))
246         ERR("GetCurrentPrintSettings failed: %08x\n", nsres);
247
248     set_default_templates(settings);
249
250     if(pvaIn) {
251         switch(V_VT(pvaIn)) {
252         case VT_BYREF|VT_ARRAY: {
253             VARIANT *opts;
254             DWORD opts_cnt;
255
256             if(V_ARRAY(pvaIn)->cDims != 1)
257                 WARN("cDims = %d\n", V_ARRAY(pvaIn)->cDims);
258
259             SafeArrayAccessData(V_ARRAY(pvaIn), (void**)&opts);
260             opts_cnt = V_ARRAY(pvaIn)->rgsabound[0].cElements;
261
262             if(opts_cnt >= 1) {
263                 switch(V_VT(opts)) {
264                 case VT_BSTR:
265                     TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts)));
266                     set_print_template(settings, V_BSTR(opts), TRUE);
267                     break;
268                 case VT_NULL:
269                     break;
270                 default:
271                     WARN("V_VT(opts) = %d\n", V_VT(opts));
272                 }
273             }
274
275             if(opts_cnt >= 2) {
276                 switch(V_VT(opts+1)) {
277                 case VT_BSTR:
278                     TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts+1)));
279                     set_print_template(settings, V_BSTR(opts+1), FALSE);
280                     break;
281                 case VT_NULL:
282                     break;
283                 default:
284                     WARN("V_VT(opts) = %d\n", V_VT(opts+1));
285                 }
286             }
287
288             if(opts_cnt >= 3)
289                 FIXME("Unsupported opts_cnt %d\n", opts_cnt);
290
291             SafeArrayUnaccessData(V_ARRAY(pvaIn));
292             break;
293         }
294         default:
295             FIXME("unsupported vt %x\n", V_VT(pvaIn));
296         }
297     }
298
299     nsres = nsIWebBrowserPrint_Print(nsprint, settings, NULL);
300     if(NS_FAILED(nsres))
301         ERR("Print failed: %08x\n", nsres);
302
303     nsIWebBrowserPrint_Release(nsprint);
304
305     return S_OK;
306 }
307
308 static HRESULT exec_print_preview(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
309 {
310     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
311     return E_NOTIMPL;
312 }
313
314 static HRESULT exec_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
315 {
316     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
317     return E_NOTIMPL;
318 }
319
320 static HRESULT exec_spell(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
321 {
322     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
323     return E_NOTIMPL;
324 }
325
326 static HRESULT exec_properties(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
327 {
328     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
329     return E_NOTIMPL;
330 }
331
332 static HRESULT exec_cut(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
333 {
334     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
335     return E_NOTIMPL;
336 }
337
338 static HRESULT exec_copy(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
339 {
340     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
341     return E_NOTIMPL;
342 }
343
344 static HRESULT exec_paste(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
345 {
346     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
347     return E_NOTIMPL;
348 }
349
350 static HRESULT exec_paste_special(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
351 {
352     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
353     return E_NOTIMPL;
354 }
355
356 static HRESULT exec_undo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
357 {
358     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
359     return E_NOTIMPL;
360 }
361
362 static HRESULT exec_rendo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
363 {
364     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
365     return E_NOTIMPL;
366 }
367
368 static HRESULT exec_select_all(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
369 {
370     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
371     return E_NOTIMPL;
372 }
373
374 static HRESULT exec_clear_selection(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
375 {
376     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
377     return E_NOTIMPL;
378 }
379
380 static HRESULT exec_zoom(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
381 {
382     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
383     return E_NOTIMPL;
384 }
385
386 static HRESULT exec_get_zoom_range(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
387 {
388     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
389     return E_NOTIMPL;
390 }
391
392 static HRESULT exec_refresh(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
393 {
394     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
395     return E_NOTIMPL;
396 }
397
398 static HRESULT exec_stop(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
399 {
400     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
401     return E_NOTIMPL;
402 }
403
404 static HRESULT exec_stop_download(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
405 {
406     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
407     return E_NOTIMPL;
408 }
409
410 static HRESULT exec_delete(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
411 {
412     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
413     return E_NOTIMPL;
414 }
415
416 static HRESULT exec_enable_interaction(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
417 {
418     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
419     return E_NOTIMPL;
420 }
421
422 static HRESULT exec_on_unload(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
423 {
424     TRACE("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
425
426     /* Tests show that we have nothing more to do here */
427
428     if(pvaOut) {
429         V_VT(pvaOut) = VT_BOOL;
430         V_BOOL(pvaOut) = VARIANT_TRUE;
431     }
432
433     return S_OK;
434 }
435
436 static HRESULT exec_show_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
437 {
438     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
439     return E_NOTIMPL;
440 }
441
442 static HRESULT exec_show_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
443 {
444     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
445     return E_NOTIMPL;
446 }
447
448 static HRESULT exec_close(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
449 {
450     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
451     return E_NOTIMPL;
452 }
453
454 static HRESULT exec_set_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
455 {
456     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
457     return E_NOTIMPL;
458 }
459
460 static HRESULT exec_get_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
461 {
462     FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
463     return E_NOTIMPL;
464 }
465
466 static void do_ns_command(NSContainer *This, const char *cmd, nsICommandParams *nsparam)
467 {
468     nsICommandManager *cmdmgr;
469     nsIInterfaceRequestor *iface_req;
470     nsresult nsres;
471
472     TRACE("(%p)\n", This);
473
474     nsres = nsIWebBrowser_QueryInterface(This->webbrowser,
475             &IID_nsIInterfaceRequestor, (void**)&iface_req);
476     if(NS_FAILED(nsres)) {
477         ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres);
478         return;
479     }
480
481     nsres = nsIInterfaceRequestor_GetInterface(iface_req, &IID_nsICommandManager,
482                                                (void**)&cmdmgr);
483     nsIInterfaceRequestor_Release(iface_req);
484     if(NS_FAILED(nsres)) {
485         ERR("Could not get nsICommandManager: %08x\n", nsres);
486         return;
487     }
488
489     nsres = nsICommandManager_DoCommand(cmdmgr, cmd, nsparam, NULL);
490     if(NS_FAILED(nsres))
491         ERR("DoCommand(%s) failed: %08x\n", debugstr_a(cmd), nsres);
492
493     nsICommandManager_Release(cmdmgr);
494 }
495
496 static nsresult get_ns_command_state(NSContainer *This, const char *cmd, nsICommandParams *nsparam)
497 {
498     nsICommandManager *cmdmgr;
499     nsIInterfaceRequestor *iface_req;
500     nsresult nsres;
501
502     nsres = nsIWebBrowser_QueryInterface(This->webbrowser,
503             &IID_nsIInterfaceRequestor, (void**)&iface_req);
504     if(NS_FAILED(nsres)) {
505         ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres);
506         return nsres;
507     }
508
509     nsres = nsIInterfaceRequestor_GetInterface(iface_req, &IID_nsICommandManager,
510                                                (void**)&cmdmgr);
511     nsIInterfaceRequestor_Release(iface_req);
512     if(NS_FAILED(nsres)) {
513         ERR("Could not get nsICommandManager: %08x\n", nsres);
514         return nsres;
515     }
516
517     nsres = nsICommandManager_GetCommandState(cmdmgr, cmd, NULL, nsparam);
518     if(NS_FAILED(nsres))
519         ERR("GetCommandState(%s) failed: %08x\n", debugstr_a(cmd), nsres);
520
521     nsICommandManager_Release(cmdmgr);
522     return nsres;
523 }
524
525 static DWORD query_edit_status(HTMLDocument *This, const char *nscmd)
526 {
527     nsICommandParams *nsparam;
528     PRBool b = FALSE;
529
530     if(This->usermode != EDITMODE || This->readystate < READYSTATE_INTERACTIVE)
531         return OLECMDF_SUPPORTED;
532
533     if(This->nscontainer && nscmd) {
534         nsparam = create_nscommand_params();
535         get_ns_command_state(This->nscontainer, nscmd, nsparam);
536
537         nsICommandParams_GetBooleanValue(nsparam, NSSTATE_ALL, &b);
538
539         nsICommandParams_Release(nsparam);
540     }
541
542     return OLECMDF_SUPPORTED | OLECMDF_ENABLED | (b ? OLECMDF_LATCHED : 0);
543 }
544
545 static DWORD query_align_status(HTMLDocument *This, const char *align_str)
546 {
547     nsICommandParams *nsparam;
548     char *align = NULL;
549
550     if(This->usermode != EDITMODE || This->readystate < READYSTATE_INTERACTIVE)
551         return OLECMDF_SUPPORTED;
552
553     if(This->nscontainer) {
554         nsparam = create_nscommand_params();
555         get_ns_command_state(This->nscontainer, NSCMD_ALIGN, nsparam);
556
557         nsICommandParams_GetCStringValue(nsparam, NSSTATE_ATTRIBUTE, &align);
558
559         nsICommandParams_Release(nsparam);
560     }
561
562     return OLECMDF_SUPPORTED | OLECMDF_ENABLED | (align && !strcmp(align_str, align) ? OLECMDF_LATCHED : 0);
563 }
564
565 static void set_ns_align(HTMLDocument *This, const char *align_str)
566 {
567     nsICommandParams *nsparam;
568
569     if(!This->nscontainer)
570         return;
571
572     nsparam = create_nscommand_params();
573     nsICommandParams_SetCStringValue(nsparam, NSSTATE_ATTRIBUTE, align_str);
574
575     do_ns_command(This->nscontainer, NSCMD_ALIGN, nsparam);
576
577     nsICommandParams_Release(nsparam);
578 }
579
580 static HRESULT exec_mshtml_copy(HTMLDocument *This)
581 {
582     FIXME("(%p)\n", This);
583     return E_NOTIMPL;
584 }
585
586 static HRESULT exec_mshtml_cut(HTMLDocument *This)
587 {
588     FIXME("(%p)\n", This);
589     return E_NOTIMPL;
590 }
591
592 static HRESULT exec_mshtml_paste(HTMLDocument *This)
593 {
594     FIXME("(%p)\n", This);
595     return E_NOTIMPL;
596 }
597
598 static HRESULT exec_fontname(HTMLDocument *This, VARIANT *in, VARIANT *out)
599 {
600     TRACE("(%p)->(%p %p)\n", This, in, out);
601
602     if(!This->nscontainer)
603         return E_FAIL;
604
605     if(in) {
606         nsICommandParams *nsparam = create_nscommand_params();
607         char *stra;
608         DWORD len;
609
610         if(V_VT(in) != VT_BSTR) {
611             FIXME("Unsupported vt=%d\n", V_VT(out));
612             return E_INVALIDARG;
613         }
614
615         len = WideCharToMultiByte(CP_ACP, 0, V_BSTR(in), -1, NULL, 0, NULL, NULL);
616         stra = mshtml_alloc(len);
617         WideCharToMultiByte(CP_ACP, 0, V_BSTR(in), -1, stra, -1, NULL, NULL);
618         nsICommandParams_SetCStringValue(nsparam, NSSTATE_ATTRIBUTE, stra);
619         mshtml_free(stra);
620
621         do_ns_command(This->nscontainer, NSCMD_FONTFACE, nsparam);
622
623         nsICommandParams_Release(nsparam);
624     }
625
626     if(out) {
627         nsICommandParams *nsparam;
628         LPWSTR strw;
629         char *stra;
630         DWORD len;
631         nsresult nsres;
632
633         if(V_VT(out) != VT_BSTR) {
634             FIXME("Unsupported vt=%d\n", V_VT(out));
635             return E_INVALIDARG;
636         }
637
638         nsparam = create_nscommand_params();
639
640         nsres = get_ns_command_state(This->nscontainer, NSCMD_FONTFACE, nsparam);
641         if(NS_FAILED(nsres))
642             return S_OK;
643
644         nsICommandParams_GetCStringValue(nsparam, NSSTATE_ATTRIBUTE, &stra);
645         nsICommandParams_Release(nsparam);
646
647         len = MultiByteToWideChar(CP_ACP, 0, stra, -1, NULL, 0);
648         strw = mshtml_alloc(len*sizeof(WCHAR));
649         MultiByteToWideChar(CP_ACP, 0, stra, -1, strw, -1);
650         nsfree(stra);
651
652         V_BSTR(out) = SysAllocString(strw);
653         mshtml_free(strw);
654     }
655
656     return S_OK;
657 }
658
659 static HRESULT exec_forecolor(HTMLDocument *This, VARIANT *in, VARIANT *out)
660 {
661     TRACE("(%p)->(%p %p)\n", This, in, out);
662
663     if(in) {
664         if(V_VT(in) == VT_I4) {
665             nsICommandParams *nsparam = create_nscommand_params();
666             char color_str[10];
667
668             sprintf(color_str, "#%02x%02x%02x",
669                     V_I4(in)&0xff, (V_I4(in)>>8)&0xff, (V_I4(in)>>16)&0xff);
670
671             nsICommandParams_SetCStringValue(nsparam, NSSTATE_ATTRIBUTE, color_str);
672             do_ns_command(This->nscontainer, NSCMD_FONTCOLOR, nsparam);
673
674             nsICommandParams_Release(nsparam);
675         }else {
676             FIXME("unsupported in vt=%d\n", V_VT(in));
677         }
678     }
679
680     if(out) {
681         FIXME("unsupported out\n");
682         return E_NOTIMPL;
683     }
684
685     return S_OK;
686 }
687
688 static HRESULT exec_fontsize(HTMLDocument *This, VARIANT *in, VARIANT *out)
689 {
690     TRACE("(%p)->(%p %p)\n", This, in, out);
691
692     if(out) {
693         WCHAR val[10] = {0};
694
695         switch(V_VT(out)) {
696         case VT_I4:
697             get_font_size(This, val);
698             V_I4(out) = strtolW(val, NULL, 10);
699             break;
700         case VT_BSTR:
701             get_font_size(This, val);
702             V_BSTR(out) = SysAllocString(val);
703             break;
704         default:
705             FIXME("unsupported vt %d\n", V_VT(out));
706         }
707     }
708
709     if(in) {
710         switch(V_VT(in)) {
711         case VT_I4: {
712             WCHAR size[10];
713             static const WCHAR format[] = {'%','d',0};
714             wsprintfW(size, format, V_I4(in));
715             set_font_size(This, size);
716             break;
717         }
718         case VT_BSTR:
719             set_font_size(This, V_BSTR(in));
720             break;
721         default:
722             FIXME("unsupported vt %d\n", V_VT(in));
723         }
724     }
725
726     return S_OK;
727 }
728
729 static HRESULT exec_bold(HTMLDocument *This)
730 {
731     TRACE("(%p)\n", This);
732
733     if(This->nscontainer)
734         do_ns_command(This->nscontainer, NSCMD_BOLD, NULL);
735
736     return S_OK;
737 }
738
739 static HRESULT exec_italic(HTMLDocument *This)
740 {
741     TRACE("(%p)\n", This);
742
743     if(This->nscontainer)
744         do_ns_command(This->nscontainer, NSCMD_ITALIC, NULL);
745
746     return S_OK;
747 }
748
749 static HRESULT exec_justifycenter(HTMLDocument *This)
750 {
751     TRACE("(%p)\n", This);
752     set_ns_align(This, NSALIGN_CENTER);
753     return S_OK;
754 }
755
756 static HRESULT exec_justifyleft(HTMLDocument *This)
757 {
758     TRACE("(%p)\n", This);
759     set_ns_align(This, NSALIGN_LEFT);
760     return S_OK;
761 }
762
763 static HRESULT exec_justifyright(HTMLDocument *This)
764 {
765     TRACE("(%p)\n", This);
766     set_ns_align(This, NSALIGN_RIGHT);
767     return S_OK;
768 }
769
770 static HRESULT exec_underline(HTMLDocument *This)
771 {
772     TRACE("(%p)\n", This);
773
774     if(This->nscontainer)
775         do_ns_command(This->nscontainer, NSCMD_UNDERLINE, NULL);
776
777     return S_OK;
778 }
779
780 static HRESULT exec_browsemode(HTMLDocument *This)
781 {
782     WARN("(%p)\n", This);
783
784     This->usermode = BROWSEMODE;
785
786     return S_OK;
787 }
788
789 static void setup_ns_editing(NSContainer *This)
790 {
791     nsIInterfaceRequestor *iface_req;
792     nsIEditingSession *editing_session = NULL;
793     nsIURIContentListener *listener = NULL;
794     nsIDOMWindow *dom_window = NULL;
795     nsresult nsres;
796
797     nsres = nsIWebBrowser_QueryInterface(This->webbrowser,
798             &IID_nsIInterfaceRequestor, (void**)&iface_req);
799     if(NS_FAILED(nsres)) {
800         ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres);
801         return;
802     }
803
804     nsres = nsIInterfaceRequestor_GetInterface(iface_req, &IID_nsIEditingSession,
805                                                (void**)&editing_session);
806     nsIInterfaceRequestor_Release(iface_req);
807     if(NS_FAILED(nsres)) {
808         ERR("Could not get nsIEditingSession: %08x\n", nsres);
809         return;
810     }
811
812     nsres = nsIWebBrowser_GetContentDOMWindow(This->webbrowser, &dom_window);
813     if(NS_FAILED(nsres)) {
814         ERR("Could not get content DOM window: %08x\n", nsres);
815         nsIEditingSession_Release(editing_session);
816         return;
817     }
818
819     nsres = nsIEditingSession_MakeWindowEditable(editing_session, dom_window, NULL, FALSE);
820     nsIEditingSession_Release(editing_session);
821     nsIDOMWindow_Release(dom_window);
822     if(NS_FAILED(nsres)) {
823         ERR("MakeWindowEditable failed: %08x\n", nsres);
824         return;
825     }
826
827     /* MakeWindowEditable changes WebBrowser's parent URI content listener.
828      * It seams to be a bug in Gecko. To workaround it we set our content
829      * listener again and Gecko's one as its parent.
830      */
831     nsIWebBrowser_GetParentURIContentListener(This->webbrowser, &listener);
832     nsIURIContentListener_SetParentContentListener(NSURICL(This), listener);
833     nsIURIContentListener_Release(listener);
834     nsIWebBrowser_SetParentURIContentListener(This->webbrowser, NSURICL(This));
835 }
836
837 static HRESULT exec_editmode(HTMLDocument *This)
838 {
839     IMoniker *mon;
840     HRESULT hres;
841
842     static const WCHAR wszAboutBlank[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
843
844     TRACE("(%p)\n", This);
845
846     This->usermode = EDITMODE;
847
848     if(This->frame)
849         IOleInPlaceFrame_SetStatusText(This->frame, NULL);
850
851     if(This->hostui) {
852         DOCHOSTUIINFO hostinfo;
853
854         memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
855         hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
856         hres = IDocHostUIHandler_GetHostInfo(This->hostui, &hostinfo);
857         if(SUCCEEDED(hres))
858             /* FIXME: use hostinfo */
859             TRACE("hostinfo = {%u %08x %08x %s %s}\n",
860                     hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
861                     debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
862     }
863
864     if(This->nscontainer)
865         setup_ns_editing(This->nscontainer);
866
867     hres = CreateURLMoniker(NULL, wszAboutBlank, &mon);
868     if(FAILED(hres)) {
869         FIXME("CreateURLMoniker failed: %08x\n", hres);
870         return hres;
871     }
872
873     return IPersistMoniker_Load(PERSISTMON(This), TRUE, mon, NULL, 0);
874 }
875
876 static HRESULT exec_baselinefont3(HTMLDocument *This)
877 {
878     FIXME("(%p)\n", This);
879     return S_OK;
880 }
881
882 static HRESULT exec_horizontalline(HTMLDocument *This)
883 {
884     TRACE("(%p)\n", This);
885
886     if(This->nscontainer)
887         do_ns_command(This->nscontainer, NSCMD_INSERTHR, NULL);
888
889     return S_OK;
890 }
891
892 static HRESULT exec_orderlist(HTMLDocument *This)
893 {
894     TRACE("(%p)\n", This);
895
896     if(This->nscontainer)
897         do_ns_command(This->nscontainer, NSCMD_OL, NULL);
898
899     return S_OK;
900 }
901
902 static HRESULT exec_unorderlist(HTMLDocument *This)
903 {
904     TRACE("(%p)\n", This);
905
906     if(This->nscontainer)
907         do_ns_command(This->nscontainer, NSCMD_UL, NULL);
908
909     return S_OK;
910 }
911
912 static HRESULT exec_indent(HTMLDocument *This)
913 {
914     TRACE("(%p)\n", This);
915
916     if(This->nscontainer)
917         do_ns_command(This->nscontainer, NSCMD_INDENT, NULL);
918
919     return S_OK;
920 }
921
922 static HRESULT exec_outdent(HTMLDocument *This)
923 {
924     TRACE("(%p)\n", This);
925
926     if(This->nscontainer)
927         do_ns_command(This->nscontainer, NSCMD_OUTDENT, NULL);
928
929     return S_OK;
930 }
931
932 static HRESULT exec_htmleditmode(HTMLDocument *This, VARIANT *in)
933 {
934     FIXME("(%p)->(%p)\n", This, in);
935     return S_OK;
936 }
937
938 static HRESULT exec_composesettings(HTMLDocument *This, VARIANT *in)
939 {
940     if(!in || V_VT(in) != VT_BSTR) {
941         WARN("invalid arg\n");
942         return E_INVALIDARG;
943     }
944
945     FIXME("%s\n", debugstr_w(V_BSTR(in)));
946
947     return S_OK;
948 }
949
950 static HRESULT exec_setdirty(HTMLDocument *This, VARIANT *in)
951 {
952     FIXME("(%p)->(%p)\n", This, in);
953     return E_NOTIMPL;
954 }
955
956 static const struct {
957     OLECMDF cmdf;
958     HRESULT (*func)(HTMLDocument*,DWORD,VARIANT*,VARIANT*);
959 } exec_table[OLECMDID_GETPRINTTEMPLATE+1] = {
960     {0},
961     { OLECMDF_SUPPORTED,                  exec_open                 }, /* OLECMDID_OPEN */
962     { OLECMDF_SUPPORTED,                  exec_new                  }, /* OLECMDID_NEW */
963     { OLECMDF_SUPPORTED,                  exec_save                 }, /* OLECMDID_SAVE */
964     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_save_as              }, /* OLECMDID_SAVEAS */
965     { OLECMDF_SUPPORTED,                  exec_save_copy_as         }, /* OLECMDID_SAVECOPYAS */
966     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_print                }, /* OLECMDID_PRINT */
967     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_print_preview        }, /* OLECMDID_PRINTPREVIEW */
968     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_page_setup           }, /* OLECMDID_PAGESETUP */
969     { OLECMDF_SUPPORTED,                  exec_spell                }, /* OLECMDID_SPELL */
970     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_properties           }, /* OLECMDID_PROPERTIES */
971     { OLECMDF_SUPPORTED,                  exec_cut                  }, /* OLECMDID_CUT */
972     { OLECMDF_SUPPORTED,                  exec_copy                 }, /* OLECMDID_COPY */
973     { OLECMDF_SUPPORTED,                  exec_paste                }, /* OLECMDID_PASTE */
974     { OLECMDF_SUPPORTED,                  exec_paste_special        }, /* OLECMDID_PASTESPECIAL */
975     { OLECMDF_SUPPORTED,                  exec_undo                 }, /* OLECMDID_UNDO */
976     { OLECMDF_SUPPORTED,                  exec_rendo                }, /* OLECMDID_REDO */
977     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_select_all           }, /* OLECMDID_SELECTALL */
978     { OLECMDF_SUPPORTED,                  exec_clear_selection      }, /* OLECMDID_CLEARSELECTION */
979     { OLECMDF_SUPPORTED,                  exec_zoom                 }, /* OLECMDID_ZOOM */
980     { OLECMDF_SUPPORTED,                  exec_get_zoom_range       }, /* OLECMDID_GETZOOMRANGE */
981     {0},
982     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_refresh              }, /* OLECMDID_REFRESH */
983     { OLECMDF_SUPPORTED|OLECMDF_ENABLED,  exec_stop                 }, /* OLECMDID_STOP */
984     {0},{0},{0},{0},{0},{0},
985     { OLECMDF_SUPPORTED,                  exec_stop_download        }, /* OLECMDID_STOPDOWNLOAD */
986     {0},{0},
987     { OLECMDF_SUPPORTED,                  exec_delete               }, /* OLECMDID_DELETE */
988     {0},{0},
989     { OLECMDF_SUPPORTED,                  exec_enable_interaction   }, /* OLECMDID_ENABLE_INTERACTION */
990     { OLECMDF_SUPPORTED,                  exec_on_unload            }, /* OLECMDID_ONUNLOAD */
991     {0},{0},{0},{0},{0},
992     { OLECMDF_SUPPORTED,                  exec_show_page_setup      }, /* OLECMDID_SHOWPAGESETUP */
993     { OLECMDF_SUPPORTED,                  exec_show_print           }, /* OLECMDID_SHOWPRINT */
994     {0},{0},
995     { OLECMDF_SUPPORTED,                  exec_close                }, /* OLECMDID_CLOSE */
996     {0},{0},{0},
997     { OLECMDF_SUPPORTED,                  exec_set_print_template   }, /* OLECMDID_SETPRINTTEMPLATE */
998     { OLECMDF_SUPPORTED,                  exec_get_print_template   }  /* OLECMDID_GETPRINTTEMPLATE */
999 };
1000
1001 static HRESULT WINAPI OleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
1002 {
1003     HTMLDocument *This = CMDTARGET_THIS(iface);
1004     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
1005 }
1006
1007 static ULONG WINAPI OleCommandTarget_AddRef(IOleCommandTarget *iface)
1008 {
1009     HTMLDocument *This = CMDTARGET_THIS(iface);
1010     return IHTMLDocument2_AddRef(HTMLDOC(This));
1011 }
1012
1013 static ULONG WINAPI OleCommandTarget_Release(IOleCommandTarget *iface)
1014 {
1015     HTMLDocument *This = CMDTARGET_THIS(iface);
1016     return IHTMLDocument_Release(HTMLDOC(This));
1017 }
1018
1019 static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1020         ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
1021 {
1022     HTMLDocument *This = CMDTARGET_THIS(iface);
1023     HRESULT hres = S_OK, hr;
1024
1025     TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
1026
1027     if(!pguidCmdGroup) {
1028         ULONG i;
1029
1030         for(i=0; i<cCmds; i++) {
1031             if(prgCmds[i].cmdID<OLECMDID_OPEN || prgCmds[i].cmdID>OLECMDID_GETPRINTTEMPLATE) {
1032                 WARN("Unsupported cmdID = %d\n", prgCmds[i].cmdID);
1033                 prgCmds[i].cmdf = 0;
1034                 hres = OLECMDERR_E_NOTSUPPORTED;
1035             }else {
1036                 if(prgCmds[i].cmdID == OLECMDID_OPEN || prgCmds[i].cmdID == OLECMDID_NEW) {
1037                     IOleCommandTarget *cmdtrg = NULL;
1038                     OLECMD olecmd;
1039
1040                     prgCmds[i].cmdf = OLECMDF_SUPPORTED;
1041                     if(This->client) {
1042                         hr = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget,
1043                                 (void**)&cmdtrg);
1044                         if(SUCCEEDED(hr)) {
1045                             olecmd.cmdID = prgCmds[i].cmdID;
1046                             olecmd.cmdf = 0;
1047
1048                             hr = IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &olecmd, NULL);
1049                             if(SUCCEEDED(hr) && olecmd.cmdf)
1050                                 prgCmds[i].cmdf = olecmd.cmdf;
1051                         }
1052                     }else {
1053                         ERR("This->client == NULL, native would crash\n");
1054                     }
1055                 }else {
1056                     prgCmds[i].cmdf = exec_table[prgCmds[i].cmdID].cmdf;
1057                     TRACE("cmdID = %d  returning %x\n", prgCmds[i].cmdID, prgCmds[i].cmdf);
1058                 }
1059                 hres = S_OK;
1060             }
1061         }
1062
1063         if(pCmdText)
1064             FIXME("Set pCmdText\n");
1065     }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
1066         ULONG i;
1067
1068         for(i=0; i<cCmds; i++) {
1069             switch(prgCmds[i].cmdID) {
1070             case IDM_COPY:
1071                 FIXME("CGID_MSHTML: IDM_COPY\n");
1072                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
1073                 break;
1074             case IDM_CUT:
1075                 FIXME("CGID_MSHTML: IDM_CUT\n");
1076                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
1077                 break;
1078             case IDM_FONTNAME:
1079                 TRACE("CGID_MSHTML: IDM_FONTNAME\n");
1080                 prgCmds[i].cmdf = query_edit_status(This, NULL);
1081                 break;
1082             case IDM_FONTSIZE:
1083                 TRACE("CGID_MSHTML: IDM_FONTSIZE\n");
1084                 prgCmds[i].cmdf = query_edit_status(This, NULL);
1085                 break;
1086             case IDM_PRINT:
1087                 FIXME("CGID_MSHTML: IDM_PRINT\n");
1088                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
1089                 break;
1090             case IDM_PASTE:
1091                 FIXME("CGID_MSHTML: IDM_PASTE\n");
1092                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
1093                 break;
1094             case IDM_BOLD:
1095                 TRACE("CGID_MSHTML: IDM_BOLD\n");
1096                 prgCmds[i].cmdf = query_edit_status(This, NSCMD_BOLD);
1097                 break;
1098             case IDM_FORECOLOR:
1099                 TRACE("CGID_MSHTML: IDM_FORECOLOR\n");
1100                 prgCmds[i].cmdf = query_edit_status(This, NULL);
1101                 break;
1102             case IDM_ITALIC:
1103                 TRACE("CGID_MSHTML: IDM_ITALIC\n");
1104                 prgCmds[i].cmdf = query_edit_status(This, NSCMD_ITALIC);
1105                 break;
1106             case IDM_JUSTIFYCENTER:
1107                 TRACE("CGID_MSHTML: IDM_JUSTIFYCENTER\n");
1108                 prgCmds[i].cmdf = query_align_status(This, NSALIGN_CENTER);
1109                 break;
1110             case IDM_JUSTIFYLEFT:
1111                 TRACE("CGID_MSHTML: IDM_JUSTIFYLEFT\n");
1112                 prgCmds[i].cmdf = query_align_status(This, NSALIGN_LEFT);
1113                 break;
1114             case IDM_JUSTIFYRIGHT:
1115                 TRACE("CGID_MSHTML: IDM_JUSTIFYRIGHT\n");
1116                 prgCmds[i].cmdf = query_align_status(This, NSALIGN_RIGHT);
1117                 break;
1118             case IDM_UNDERLINE:
1119                 TRACE("CGID_MSHTML: IDM_UNDERLINE\n");
1120                 prgCmds[i].cmdf = query_edit_status(This, NSCMD_UNDERLINE);
1121                 break;
1122             case IDM_HORIZONTALLINE:
1123                 TRACE("CGID_MSHTML: IDM_HORIZONTALLINE\n");
1124                 prgCmds[i].cmdf = query_edit_status(This, NULL);
1125                 break;
1126             case IDM_ORDERLIST:
1127                 TRACE("CGID_MSHTML: IDM_ORDERLIST\n");
1128                 prgCmds[i].cmdf = query_edit_status(This, NSCMD_OL);
1129                 break;
1130             case IDM_UNORDERLIST:
1131                 TRACE("CGID_MSHTML: IDM_HORIZONTALLINE\n");
1132                 prgCmds[i].cmdf = query_edit_status(This, NSCMD_UL);
1133                 break;
1134             case IDM_INDENT:
1135                 TRACE("CGID_MSHTML: IDM_INDENT\n");
1136                 prgCmds[i].cmdf = query_edit_status(This, NULL);
1137                 break;
1138             case IDM_OUTDENT:
1139                 TRACE("CGID_MSHTML: IDM_OUTDENT\n");
1140                 prgCmds[i].cmdf = query_edit_status(This, NULL);
1141                 break;
1142             case IDM_BLOCKDIRLTR:
1143                 FIXME("CGID_MSHTML: IDM_BLOCKDIRLTR\n");
1144                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
1145                 break;
1146             case IDM_BLOCKDIRRTL:
1147                 FIXME("CGID_MSHTML: IDM_BLOCKDIRRTL\n");
1148                 prgCmds[i].cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
1149                 break;
1150             default:
1151                 FIXME("CGID_MSHTML: unsupported cmdID %d\n", prgCmds[i].cmdID);
1152                 prgCmds[i].cmdf = 0;
1153             }
1154         }
1155
1156         hres = prgCmds[i-1].cmdf ? S_OK : OLECMDERR_E_NOTSUPPORTED;
1157
1158         if(pCmdText)
1159             FIXME("Set pCmdText\n");
1160     }else {
1161         FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
1162         hres = OLECMDERR_E_UNKNOWNGROUP;
1163     }
1164
1165     return hres;
1166 }
1167
1168 static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
1169         DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1170 {
1171     HTMLDocument *This = CMDTARGET_THIS(iface);
1172
1173     if(!pguidCmdGroup) {
1174         if(nCmdID<OLECMDID_OPEN || nCmdID>OLECMDID_GETPRINTTEMPLATE || !exec_table[nCmdID].func) {
1175             WARN("Unsupported cmdID = %d\n", nCmdID);
1176             return OLECMDERR_E_NOTSUPPORTED;
1177         }
1178
1179         return exec_table[nCmdID].func(This, nCmdexecopt, pvaIn, pvaOut);
1180     }else if(IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) {
1181         FIXME("unsupported nCmdID %d of CGID_Explorer group\n", nCmdID);
1182         TRACE("%p %p\n", pvaIn, pvaOut);
1183         return OLECMDERR_E_NOTSUPPORTED;
1184     }else if(IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup)) {
1185         FIXME("unsupported nCmdID %d of CGID_ShellDocView group\n", nCmdID);
1186         return OLECMDERR_E_NOTSUPPORTED;
1187     }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
1188         switch(nCmdID) {
1189         case IDM_COPY:
1190             if(pvaIn || pvaOut)
1191                 FIXME("unsupported arguments\n");
1192             return exec_mshtml_copy(This);
1193         case IDM_CUT:
1194             if(pvaIn || pvaOut)
1195                 FIXME("unsupported arguments\n");
1196             return exec_mshtml_cut(This);
1197         case IDM_FONTNAME:
1198             return exec_fontname(This, pvaIn, pvaOut);
1199         case IDM_FONTSIZE:
1200             return exec_fontsize(This, pvaIn, pvaOut);
1201         case IDM_PASTE:
1202             if(pvaIn || pvaOut)
1203                 FIXME("unsupported arguments\n");
1204             return exec_mshtml_paste(This);
1205         case IDM_PRINT:
1206             return exec_print(This, nCmdexecopt, pvaIn, pvaOut);
1207         case IDM_BOLD:
1208             if(pvaIn || pvaOut)
1209                 FIXME("unsupported arguments\n");
1210             return exec_bold(This);
1211         case IDM_FORECOLOR:
1212             return exec_forecolor(This, pvaIn, pvaOut);
1213         case IDM_ITALIC:
1214             if(pvaIn || pvaOut)
1215                 FIXME("unsupported arguments\n");
1216             return exec_italic(This);
1217         case IDM_JUSTIFYCENTER:
1218             if(pvaIn || pvaOut)
1219                 FIXME("unsupported arguments\n");
1220             return exec_justifycenter(This);
1221         case IDM_JUSTIFYLEFT:
1222             if(pvaIn || pvaOut)
1223                 FIXME("unsupported arguments\n");
1224             return exec_justifyleft(This);
1225         case IDM_JUSTIFYRIGHT:
1226             if(pvaIn || pvaOut)
1227                 FIXME("unsupported arguments\n");
1228             return exec_justifyright(This);
1229         case IDM_UNDERLINE:
1230             if(pvaIn || pvaOut)
1231                 FIXME("unsupported arguments\n");
1232             return exec_underline(This);
1233         case IDM_BROWSEMODE:
1234             if(pvaIn || pvaOut)
1235                 FIXME("unsupported arguments\n");
1236             return exec_browsemode(This);
1237         case IDM_EDITMODE:
1238             if(pvaIn || pvaOut)
1239                 FIXME("unsupported arguments\n");
1240             return exec_editmode(This);
1241         case IDM_BASELINEFONT3:
1242             return exec_baselinefont3(This);
1243         case IDM_HORIZONTALLINE:
1244             if(pvaIn || pvaOut)
1245                 FIXME("unsupported arguments\n");
1246             return exec_horizontalline(This);
1247         case IDM_ORDERLIST:
1248             if(pvaIn || pvaOut)
1249                 FIXME("unsupported arguments\n");
1250             return exec_orderlist(This);
1251         case IDM_UNORDERLIST:
1252             if(pvaIn || pvaOut)
1253                 FIXME("unsupported arguments\n");
1254             return exec_unorderlist(This);
1255         case IDM_INDENT:
1256             if(pvaIn || pvaOut)
1257                 FIXME("unsupported arguments\n");
1258             return exec_indent(This);
1259         case IDM_OUTDENT:
1260             if(pvaIn || pvaOut)
1261                 FIXME("unsupported arguments\n");
1262             return exec_outdent(This);
1263         case IDM_HTMLEDITMODE:
1264             if(pvaOut)
1265                 FIXME("unsupported arguments\n");
1266             return exec_htmleditmode(This, pvaIn);
1267         case IDM_COMPOSESETTINGS:
1268             if(pvaOut)
1269                 FIXME("unsupported arguments\n");
1270             return exec_composesettings(This, pvaIn);
1271         case IDM_SETDIRTY:
1272             if(pvaOut)
1273                 FIXME("unsupported arguments\n");
1274             return exec_setdirty(This, pvaIn);
1275         default:
1276             FIXME("unsupported nCmdID %d of CGID_MSHTML group\n", nCmdID);
1277             return OLECMDERR_E_NOTSUPPORTED;
1278         }
1279     }
1280
1281     FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
1282     return OLECMDERR_E_UNKNOWNGROUP;
1283 }
1284
1285 #undef CMDTARGET_THIS
1286
1287 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
1288     OleCommandTarget_QueryInterface,
1289     OleCommandTarget_AddRef,
1290     OleCommandTarget_Release,
1291     OleCommandTarget_QueryStatus,
1292     OleCommandTarget_Exec
1293 };
1294
1295 void HTMLDocument_OleCmd_Init(HTMLDocument *This)
1296 {
1297     This->lpOleCommandTargetVtbl = &OleCommandTargetVtbl;
1298 }