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