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