[CRT] Massively improve performance of rand_s
[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 #define NSCMD_SELECTALL "cmd_selectAll"
23
24 void do_ns_command(HTMLDocument *This, const char *cmd, nsICommandParams *nsparam)
25 {
26 nsICommandManager *cmdmgr;
27 nsresult nsres;
28
29 TRACE("(%p)\n", This);
30
31 if(!This->doc_obj || !This->doc_obj->nscontainer)
32 return;
33
34 nsres = get_nsinterface((nsISupports*)This->doc_obj->nscontainer->webbrowser, &IID_nsICommandManager, (void**)&cmdmgr);
35 if(NS_FAILED(nsres)) {
36 ERR("Could not get nsICommandManager: %08x\n", nsres);
37 return;
38 }
39
40 nsres = nsICommandManager_DoCommand(cmdmgr, cmd, nsparam, This->window->nswindow);
41 if(NS_FAILED(nsres))
42 ERR("DoCommand(%s) failed: %08x\n", debugstr_a(cmd), nsres);
43
44 nsICommandManager_Release(cmdmgr);
45 }
46
47 static nsIClipboardCommands *get_clipboard_commands(HTMLDocument *doc)
48 {
49 nsIClipboardCommands *clipboard_commands;
50 nsIDocShell *doc_shell;
51 nsresult nsres;
52
53 nsres = get_nsinterface((nsISupports*)doc->window->nswindow, &IID_nsIDocShell, (void**)&doc_shell);
54 if(NS_FAILED(nsres)) {
55 ERR("Could not get nsIDocShell interface\n");
56 return NULL;
57 }
58
59 nsres = nsIDocShell_QueryInterface(doc_shell, &IID_nsIClipboardCommands, (void**)&clipboard_commands);
60 nsIDocShell_Release(doc_shell);
61 if(NS_FAILED(nsres)) {
62 ERR("Could not get nsIClipboardCommands interface\n");
63 return NULL;
64 }
65
66 return clipboard_commands;
67 }
68
69 /**********************************************************
70 * IOleCommandTarget implementation
71 */
72
73 static inline HTMLDocument *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
74 {
75 return CONTAINING_RECORD(iface, HTMLDocument, IOleCommandTarget_iface);
76 }
77
78 static HRESULT exec_open(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
79 {
80 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
81 return E_NOTIMPL;
82 }
83
84 static HRESULT exec_new(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
85 {
86 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
87 return E_NOTIMPL;
88 }
89
90 static HRESULT exec_save(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
91 {
92 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
93 return E_NOTIMPL;
94 }
95
96 static HRESULT exec_save_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
97 {
98 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
99 return E_NOTIMPL;
100 }
101
102 static HRESULT exec_save_copy_as(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
103 {
104 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
105 return E_NOTIMPL;
106 }
107
108 static nsresult set_head_text(nsIPrintSettings *settings, LPCWSTR template, BOOL head, int pos)
109 {
110 if(head) {
111 switch(pos) {
112 case 0:
113 return nsIPrintSettings_SetHeaderStrLeft(settings, template);
114 case 1:
115 return nsIPrintSettings_SetHeaderStrRight(settings, template);
116 case 2:
117 return nsIPrintSettings_SetHeaderStrCenter(settings, template);
118 }
119 }else {
120 switch(pos) {
121 case 0:
122 return nsIPrintSettings_SetFooterStrLeft(settings, template);
123 case 1:
124 return nsIPrintSettings_SetFooterStrRight(settings, template);
125 case 2:
126 return nsIPrintSettings_SetFooterStrCenter(settings, template);
127 }
128 }
129
130 return NS_OK;
131 }
132
133 static void set_print_template(nsIPrintSettings *settings, LPCWSTR template, BOOL head)
134 {
135 PRUnichar nstemplate[200]; /* FIXME: Use dynamic allocation */
136 PRUnichar *p = nstemplate;
137 LPCWSTR ptr=template;
138 int pos=0;
139
140 while(*ptr) {
141 if(*ptr != '&') {
142 *p++ = *ptr++;
143 continue;
144 }
145
146 switch(*++ptr) {
147 case '&':
148 *p++ = '&';
149 *p++ = '&';
150 ptr++;
151 break;
152 case 'b': /* change align */
153 ptr++;
154 *p = 0;
155 set_head_text(settings, nstemplate, head, pos);
156 p = nstemplate;
157 pos++;
158 break;
159 case 'd': { /* short date */
160 SYSTEMTIME systime;
161 GetLocalTime(&systime);
162 GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &systime, NULL, p,
163 sizeof(nstemplate)-(p-nstemplate)*sizeof(WCHAR));
164 p += strlenW(p);
165 ptr++;
166 break;
167 }
168 case 'p': /* page number */
169 *p++ = '&';
170 *p++ = 'P';
171 ptr++;
172 break;
173 case 'P': /* page count */
174 *p++ = '?'; /* FIXME */
175 ptr++;
176 break;
177 case 'u':
178 *p++ = '&';
179 *p++ = 'U';
180 ptr++;
181 break;
182 case 'w':
183 /* FIXME: set window title */
184 ptr++;
185 break;
186 default:
187 *p++ = '&';
188 *p++ = *ptr++;
189 }
190 }
191
192 *p = 0;
193 set_head_text(settings, nstemplate, head, pos);
194
195 while(++pos < 3)
196 set_head_text(settings, p, head, pos);
197 }
198
199 static void set_default_templates(nsIPrintSettings *settings)
200 {
201 WCHAR buf[64];
202
203 static const PRUnichar empty[] = {0};
204
205 nsIPrintSettings_SetHeaderStrLeft(settings, empty);
206 nsIPrintSettings_SetHeaderStrRight(settings, empty);
207 nsIPrintSettings_SetHeaderStrCenter(settings, empty);
208 nsIPrintSettings_SetFooterStrLeft(settings, empty);
209 nsIPrintSettings_SetFooterStrRight(settings, empty);
210 nsIPrintSettings_SetFooterStrCenter(settings, empty);
211
212 if(LoadStringW(get_shdoclc(), IDS_PRINT_HEADER_TEMPLATE, buf,
213 sizeof(buf)/sizeof(WCHAR)))
214 set_print_template(settings, buf, TRUE);
215
216
217 if(LoadStringW(get_shdoclc(), IDS_PRINT_FOOTER_TEMPLATE, buf,
218 sizeof(buf)/sizeof(WCHAR)))
219 set_print_template(settings, buf, FALSE);
220
221 }
222
223 static HRESULT exec_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
224 {
225 nsIWebBrowserPrint *nsprint;
226 nsIPrintSettings *settings;
227 nsresult nsres;
228
229 TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
230
231 if(pvaOut)
232 FIXME("unsupported pvaOut\n");
233
234 if(!This->doc_obj->nscontainer)
235 return S_OK;
236
237 nsres = get_nsinterface((nsISupports*)This->doc_obj->nscontainer->webbrowser, &IID_nsIWebBrowserPrint,
238 (void**)&nsprint);
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("opts = %s\n", debugstr_variant(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("opts[1] = %s\n", debugstr_variant(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 arg %s\n", debugstr_variant(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 TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
341
342 do_ns_command(This, NSCMD_COPY, NULL);
343 return S_OK;
344 }
345
346 static HRESULT exec_paste(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
347 {
348 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
349 return E_NOTIMPL;
350 }
351
352 static HRESULT exec_paste_special(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
353 {
354 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
355 return E_NOTIMPL;
356 }
357
358 static HRESULT exec_undo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
359 {
360 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
361 return E_NOTIMPL;
362 }
363
364 static HRESULT exec_rendo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
365 {
366 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
367 return E_NOTIMPL;
368 }
369
370 static HRESULT exec_select_all(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *in, VARIANT *out)
371 {
372 TRACE("(%p)\n", This);
373
374 if(in || out)
375 FIXME("unsupported args\n");
376
377 if(This->doc_obj->nscontainer)
378 do_ns_command(This, NSCMD_SELECTALL, NULL);
379
380 update_doc(This, UPDATE_UI);
381 return S_OK;
382 }
383
384 static HRESULT exec_clear_selection(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
385 {
386 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
387 return E_NOTIMPL;
388 }
389
390 static HRESULT exec_zoom(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
391 {
392 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
393 return E_NOTIMPL;
394 }
395
396 static HRESULT exec_get_zoom_range(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
397 {
398 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
399 return E_NOTIMPL;
400 }
401
402 typedef struct {
403 task_t header;
404 HTMLOuterWindow *window;
405 }refresh_task_t;
406
407 static void refresh_proc(task_t *_task)
408 {
409 refresh_task_t *task = (refresh_task_t*)_task;
410 HTMLOuterWindow *window = task->window;
411
412 TRACE("%p\n", window);
413
414 window->readystate = READYSTATE_UNINITIALIZED;
415
416 if(window->doc_obj && window->doc_obj->client_cmdtrg) {
417 VARIANT var;
418
419 V_VT(&var) = VT_I4;
420 V_I4(&var) = 0;
421 IOleCommandTarget_Exec(window->doc_obj->client_cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL);
422 }
423
424 load_uri(task->window, task->window->uri, BINDING_REFRESH|BINDING_NOFRAG);
425 }
426
427 static void refresh_destr(task_t *_task)
428 {
429 refresh_task_t *task = (refresh_task_t*)_task;
430
431 IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface);
432 heap_free(task);
433 }
434
435 static HRESULT exec_refresh(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
436 {
437 refresh_task_t *task;
438 HRESULT hres;
439
440 TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
441
442 if(This->doc_obj->client) {
443 IOleCommandTarget *olecmd;
444
445 hres = IOleClientSite_QueryInterface(This->doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd);
446 if(SUCCEEDED(hres)) {
447 hres = IOleCommandTarget_Exec(olecmd, &CGID_DocHostCommandHandler, 2300, nCmdexecopt, pvaIn, pvaOut);
448 IOleCommandTarget_Release(olecmd);
449 if(SUCCEEDED(hres))
450 return S_OK;
451 }
452 }
453
454 if(!This->window)
455 return E_UNEXPECTED;
456
457 task = heap_alloc(sizeof(*task));
458 if(!task)
459 return E_OUTOFMEMORY;
460
461 IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface);
462 task->window = This->window;
463
464 return push_task(&task->header, refresh_proc, refresh_destr, This->window->task_magic);
465 }
466
467 static HRESULT exec_stop(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
468 {
469 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
470 return E_NOTIMPL;
471 }
472
473 static HRESULT exec_stop_download(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
474 {
475 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
476 return E_NOTIMPL;
477 }
478
479 static HRESULT exec_find(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
480 {
481 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
482 return E_NOTIMPL;
483 }
484
485 static HRESULT exec_delete(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
486 {
487 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
488 return E_NOTIMPL;
489 }
490
491 static HRESULT exec_enable_interaction(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
492 {
493 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
494 return E_NOTIMPL;
495 }
496
497 static HRESULT exec_on_unload(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
498 {
499 TRACE("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
500
501 /* Tests show that we have nothing more to do here */
502
503 if(pvaOut) {
504 V_VT(pvaOut) = VT_BOOL;
505 V_BOOL(pvaOut) = VARIANT_TRUE;
506 }
507
508 return S_OK;
509 }
510
511 static HRESULT exec_show_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
512 {
513 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
514 return E_NOTIMPL;
515 }
516
517 static HRESULT exec_show_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
518 {
519 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
520 return E_NOTIMPL;
521 }
522
523 static HRESULT exec_close(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
524 {
525 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
526 return E_NOTIMPL;
527 }
528
529 static HRESULT exec_set_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
530 {
531 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
532 return E_NOTIMPL;
533 }
534
535 static HRESULT exec_get_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
536 {
537 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut);
538 return E_NOTIMPL;
539 }
540
541 static HRESULT exec_optical_zoom(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
542 {
543 TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
544
545 if(!pvaIn || V_VT(pvaIn) != VT_I4) {
546 FIXME("Unsupported argument %s\n", debugstr_variant(pvaIn));
547 return E_NOTIMPL;
548 }
549
550 set_viewer_zoom(This->doc_obj->nscontainer, (float)V_I4(pvaIn)/100);
551 return S_OK;
552 }
553
554 static HRESULT query_mshtml_copy(HTMLDocument *This, OLECMD *cmd)
555 {
556 FIXME("(%p)\n", This);
557 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
558 return S_OK;
559 }
560
561 static HRESULT exec_mshtml_copy(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
562 {
563 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
564
565 if(This->doc_obj->usermode == EDITMODE)
566 return editor_exec_copy(This, cmdexecopt, in, out);
567
568 do_ns_command(This, NSCMD_COPY, NULL);
569 return S_OK;
570 }
571
572 static HRESULT query_mshtml_cut(HTMLDocument *This, OLECMD *cmd)
573 {
574 FIXME("(%p)\n", This);
575 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
576 return S_OK;
577 }
578
579 static HRESULT exec_mshtml_cut(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
580 {
581 nsIClipboardCommands *clipboard_commands;
582 nsresult nsres;
583
584 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
585
586 if(This->doc_obj->usermode == EDITMODE)
587 return editor_exec_cut(This, cmdexecopt, in, out);
588
589 clipboard_commands = get_clipboard_commands(This);
590 if(!clipboard_commands)
591 return E_UNEXPECTED;
592
593 nsres = nsIClipboardCommands_CutSelection(clipboard_commands);
594 nsIClipboardCommands_Release(clipboard_commands);
595 if(NS_FAILED(nsres)) {
596 ERR("Paste failed: %08x\n", nsres);
597 return E_FAIL;
598 }
599
600 return S_OK;
601 }
602
603 static HRESULT query_mshtml_paste(HTMLDocument *This, OLECMD *cmd)
604 {
605 FIXME("(%p)\n", This);
606 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
607 return S_OK;
608 }
609
610 static HRESULT exec_mshtml_paste(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
611 {
612 nsIClipboardCommands *clipboard_commands;
613 nsresult nsres;
614
615 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
616
617 if(This->doc_obj->usermode == EDITMODE)
618 return editor_exec_paste(This, cmdexecopt, in, out);
619
620 clipboard_commands = get_clipboard_commands(This);
621 if(!clipboard_commands)
622 return E_UNEXPECTED;
623
624 nsres = nsIClipboardCommands_Paste(clipboard_commands);
625 nsIClipboardCommands_Release(clipboard_commands);
626 if(NS_FAILED(nsres)) {
627 ERR("Paste failed: %08x\n", nsres);
628 return E_FAIL;
629 }
630
631 return S_OK;
632 }
633
634 static HRESULT query_selall_status(HTMLDocument *This, OLECMD *cmd)
635 {
636 TRACE("(%p)->(%p)\n", This, cmd);
637
638 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
639 return S_OK;
640 }
641
642 static HRESULT exec_browsemode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
643 {
644 WARN("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
645
646 if(in || out)
647 FIXME("unsupported args\n");
648
649 This->doc_obj->usermode = BROWSEMODE;
650
651 return S_OK;
652 }
653
654 static HRESULT exec_editmode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
655 {
656 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
657
658 if(in || out)
659 FIXME("unsupported args\n");
660
661 return setup_edit_mode(This->doc_obj);
662 }
663
664 static HRESULT exec_htmleditmode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
665 {
666 FIXME("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
667 return S_OK;
668 }
669
670 static HRESULT exec_baselinefont3(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
671 {
672 FIXME("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);
673 return S_OK;
674 }
675
676 static HRESULT exec_respectvisibility_indesign(HTMLDocument *This, DWORD cmdexecopt,
677 VARIANT *in, VARIANT *out)
678 {
679 TRACE("(%p)->(%x %s %p)\n", This, cmdexecopt, debugstr_variant(in), out);
680
681 /* This is turned on by default in Gecko. */
682 if(!in || V_VT(in) != VT_BOOL || !V_BOOL(in))
683 FIXME("Unsupported argument %s\n", debugstr_variant(in));
684
685 return S_OK;
686 }
687
688 static HRESULT query_enabled_stub(HTMLDocument *This, OLECMD *cmd)
689 {
690 switch(cmd->cmdID) {
691 case IDM_PRINT:
692 FIXME("CGID_MSHTML: IDM_PRINT\n");
693 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
694 break;
695 case IDM_BLOCKDIRLTR:
696 FIXME("CGID_MSHTML: IDM_BLOCKDIRLTR\n");
697 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
698 break;
699 case IDM_BLOCKDIRRTL:
700 FIXME("CGID_MSHTML: IDM_BLOCKDIRRTL\n");
701 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
702 break;
703 }
704
705 return S_OK;
706 }
707
708 static const struct {
709 OLECMDF cmdf;
710 HRESULT (*func)(HTMLDocument*,DWORD,VARIANT*,VARIANT*);
711 } exec_table[] = {
712 {0},
713 { OLECMDF_SUPPORTED, exec_open }, /* OLECMDID_OPEN */
714 { OLECMDF_SUPPORTED, exec_new }, /* OLECMDID_NEW */
715 { OLECMDF_SUPPORTED, exec_save }, /* OLECMDID_SAVE */
716 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_save_as }, /* OLECMDID_SAVEAS */
717 { OLECMDF_SUPPORTED, exec_save_copy_as }, /* OLECMDID_SAVECOPYAS */
718 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_print }, /* OLECMDID_PRINT */
719 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_print_preview }, /* OLECMDID_PRINTPREVIEW */
720 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_page_setup }, /* OLECMDID_PAGESETUP */
721 { OLECMDF_SUPPORTED, exec_spell }, /* OLECMDID_SPELL */
722 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_properties }, /* OLECMDID_PROPERTIES */
723 { OLECMDF_SUPPORTED, exec_cut }, /* OLECMDID_CUT */
724 { OLECMDF_SUPPORTED, exec_copy }, /* OLECMDID_COPY */
725 { OLECMDF_SUPPORTED, exec_paste }, /* OLECMDID_PASTE */
726 { OLECMDF_SUPPORTED, exec_paste_special }, /* OLECMDID_PASTESPECIAL */
727 { OLECMDF_SUPPORTED, exec_undo }, /* OLECMDID_UNDO */
728 { OLECMDF_SUPPORTED, exec_rendo }, /* OLECMDID_REDO */
729 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_select_all }, /* OLECMDID_SELECTALL */
730 { OLECMDF_SUPPORTED, exec_clear_selection }, /* OLECMDID_CLEARSELECTION */
731 { OLECMDF_SUPPORTED, exec_zoom }, /* OLECMDID_ZOOM */
732 { OLECMDF_SUPPORTED, exec_get_zoom_range }, /* OLECMDID_GETZOOMRANGE */
733 {0},
734 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_refresh }, /* OLECMDID_REFRESH */
735 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_stop }, /* OLECMDID_STOP */
736 {0},{0},{0},{0},{0},{0},
737 { OLECMDF_SUPPORTED, exec_stop_download }, /* OLECMDID_STOPDOWNLOAD */
738 {0},
739 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_find }, /* OLECMDID_FIND */
740 { OLECMDF_SUPPORTED, exec_delete }, /* OLECMDID_DELETE */
741 {0},{0},
742 { OLECMDF_SUPPORTED, exec_enable_interaction }, /* OLECMDID_ENABLE_INTERACTION */
743 { OLECMDF_SUPPORTED, exec_on_unload }, /* OLECMDID_ONUNLOAD */
744 {0},{0},{0},{0},{0},
745 { OLECMDF_SUPPORTED, exec_show_page_setup }, /* OLECMDID_SHOWPAGESETUP */
746 { OLECMDF_SUPPORTED, exec_show_print }, /* OLECMDID_SHOWPRINT */
747 {0},{0},
748 { OLECMDF_SUPPORTED, exec_close }, /* OLECMDID_CLOSE */
749 {0},{0},{0},
750 { OLECMDF_SUPPORTED, exec_set_print_template }, /* OLECMDID_SETPRINTTEMPLATE */
751 { OLECMDF_SUPPORTED, exec_get_print_template }, /* OLECMDID_GETPRINTTEMPLATE */
752 {0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
753 { 0, /* not reported as supported */ exec_optical_zoom } /* OLECMDID_OPTICAL_ZOOM */
754 };
755
756 static const cmdtable_t base_cmds[] = {
757 {IDM_COPY, query_mshtml_copy, exec_mshtml_copy},
758 {IDM_PASTE, query_mshtml_paste, exec_mshtml_paste},
759 {IDM_CUT, query_mshtml_cut, exec_mshtml_cut},
760 {IDM_SELECTALL, query_selall_status, exec_select_all},
761 {IDM_BROWSEMODE, NULL, exec_browsemode},
762 {IDM_EDITMODE, NULL, exec_editmode},
763 {IDM_PRINT, query_enabled_stub, exec_print},
764 {IDM_HTMLEDITMODE, NULL, exec_htmleditmode},
765 {IDM_BASELINEFONT3, NULL, exec_baselinefont3},
766 {IDM_BLOCKDIRLTR, query_enabled_stub, NULL},
767 {IDM_BLOCKDIRRTL, query_enabled_stub, NULL},
768 {IDM_RESPECTVISIBILITY_INDESIGN, NULL, exec_respectvisibility_indesign},
769 {0,NULL,NULL}
770 };
771
772 static HRESULT WINAPI OleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv)
773 {
774 HTMLDocument *This = impl_from_IOleCommandTarget(iface);
775 return htmldoc_query_interface(This, riid, ppv);
776 }
777
778 static ULONG WINAPI OleCommandTarget_AddRef(IOleCommandTarget *iface)
779 {
780 HTMLDocument *This = impl_from_IOleCommandTarget(iface);
781 return htmldoc_addref(This);
782 }
783
784 static ULONG WINAPI OleCommandTarget_Release(IOleCommandTarget *iface)
785 {
786 HTMLDocument *This = impl_from_IOleCommandTarget(iface);
787 return htmldoc_release(This);
788 }
789
790 static HRESULT query_from_table(HTMLDocument *This, const cmdtable_t *cmdtable, OLECMD *cmd)
791 {
792 const cmdtable_t *iter = cmdtable;
793
794 cmd->cmdf = 0;
795
796 while(iter->id && iter->id != cmd->cmdID)
797 iter++;
798
799 if(!iter->id || !iter->query)
800 return OLECMDERR_E_NOTSUPPORTED;
801
802 return iter->query(This, cmd);
803 }
804
805 static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
806 ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
807 {
808 HTMLDocument *This = impl_from_IOleCommandTarget(iface);
809 HRESULT hres;
810
811 TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
812
813 if(pCmdText)
814 FIXME("Unsupported pCmdText\n");
815 if(!cCmds)
816 return S_OK;
817
818 if(!pguidCmdGroup) {
819 ULONG i;
820
821 for(i=0; i<cCmds; i++) {
822 if(prgCmds[i].cmdID < OLECMDID_OPEN || prgCmds[i].cmdID >= sizeof(exec_table)/sizeof(*exec_table)) {
823 WARN("Unsupported cmdID = %d\n", prgCmds[i].cmdID);
824 prgCmds[i].cmdf = 0;
825 }else {
826 if(prgCmds[i].cmdID == OLECMDID_OPEN || prgCmds[i].cmdID == OLECMDID_NEW) {
827 IOleCommandTarget *cmdtrg = NULL;
828 OLECMD olecmd;
829
830 prgCmds[i].cmdf = OLECMDF_SUPPORTED;
831 if(This->doc_obj->client) {
832 hres = IOleClientSite_QueryInterface(This->doc_obj->client, &IID_IOleCommandTarget,
833 (void**)&cmdtrg);
834 if(SUCCEEDED(hres)) {
835 olecmd.cmdID = prgCmds[i].cmdID;
836 olecmd.cmdf = 0;
837
838 hres = IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &olecmd, NULL);
839 if(SUCCEEDED(hres) && olecmd.cmdf)
840 prgCmds[i].cmdf = olecmd.cmdf;
841 }
842 }else {
843 ERR("This->client == NULL, native would crash\n");
844 }
845 }else {
846 prgCmds[i].cmdf = exec_table[prgCmds[i].cmdID].cmdf;
847 TRACE("cmdID = %d returning %x\n", prgCmds[i].cmdID, prgCmds[i].cmdf);
848 }
849 }
850 }
851
852 return (prgCmds[cCmds-1].cmdf & OLECMDF_SUPPORTED) ? S_OK : OLECMDERR_E_NOTSUPPORTED;
853 }
854
855 if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
856 ULONG i;
857
858 for(i=0; i<cCmds; i++) {
859 hres = query_from_table(This, base_cmds, prgCmds+i);
860 if(hres == OLECMDERR_E_NOTSUPPORTED)
861 hres = query_from_table(This, editmode_cmds, prgCmds+i);
862 if(hres == OLECMDERR_E_NOTSUPPORTED)
863 FIXME("CGID_MSHTML: unsupported cmdID %d\n", prgCmds[i].cmdID);
864 }
865
866 return (prgCmds[cCmds-1].cmdf & OLECMDF_SUPPORTED) ? S_OK : OLECMDERR_E_NOTSUPPORTED;
867 }
868
869 FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
870 return OLECMDERR_E_UNKNOWNGROUP;
871 }
872
873 static HRESULT exec_from_table(HTMLDocument *This, const cmdtable_t *cmdtable, DWORD cmdid,
874 DWORD cmdexecopt, VARIANT *in, VARIANT *out)
875 {
876 const cmdtable_t *iter = cmdtable;
877
878 while(iter->id && iter->id != cmdid)
879 iter++;
880
881 if(!iter->id || !iter->exec)
882 return OLECMDERR_E_NOTSUPPORTED;
883
884 return iter->exec(This, cmdexecopt, in, out);
885 }
886
887 static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
888 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
889 {
890 HTMLDocument *This = impl_from_IOleCommandTarget(iface);
891
892 if(!pguidCmdGroup) {
893 if(nCmdID < OLECMDID_OPEN || nCmdID >= sizeof(exec_table)/sizeof(*exec_table) || !exec_table[nCmdID].func) {
894 WARN("Unsupported cmdID = %d\n", nCmdID);
895 return OLECMDERR_E_NOTSUPPORTED;
896 }
897
898 return exec_table[nCmdID].func(This, nCmdexecopt, pvaIn, pvaOut);
899 }else if(IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) {
900 FIXME("unsupported nCmdID %d of CGID_Explorer group\n", nCmdID);
901 TRACE("%p %p\n", pvaIn, pvaOut);
902 return OLECMDERR_E_NOTSUPPORTED;
903 }else if(IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup)) {
904 FIXME("unsupported nCmdID %d of CGID_ShellDocView group\n", nCmdID);
905 return OLECMDERR_E_NOTSUPPORTED;
906 }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) {
907 HRESULT hres = exec_from_table(This, base_cmds, nCmdID, nCmdexecopt, pvaIn, pvaOut);
908 if(hres == OLECMDERR_E_NOTSUPPORTED)
909 hres = exec_from_table(This, editmode_cmds, nCmdID,
910 nCmdexecopt, pvaIn, pvaOut);
911 if(hres == OLECMDERR_E_NOTSUPPORTED)
912 FIXME("unsupported nCmdID %d of CGID_MSHTML group\n", nCmdID);
913
914 return hres;
915 }
916
917 FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
918 return OLECMDERR_E_UNKNOWNGROUP;
919 }
920
921 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
922 OleCommandTarget_QueryInterface,
923 OleCommandTarget_AddRef,
924 OleCommandTarget_Release,
925 OleCommandTarget_QueryStatus,
926 OleCommandTarget_Exec
927 };
928
929 void show_context_menu(HTMLDocumentObj *This, DWORD dwID, POINT *ppt, IDispatch *elem)
930 {
931 HMENU menu_res, menu;
932 DWORD cmdid;
933
934 if(This->hostui && S_OK == IDocHostUIHandler_ShowContextMenu(This->hostui,
935 dwID, ppt, (IUnknown*)&This->basedoc.IOleCommandTarget_iface, elem))
936 return;
937
938 menu_res = LoadMenuW(get_shdoclc(), MAKEINTRESOURCEW(IDR_BROWSE_CONTEXT_MENU));
939 menu = GetSubMenu(menu_res, dwID);
940
941 cmdid = TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
942 ppt->x, ppt->y, 0, This->hwnd, NULL);
943 DestroyMenu(menu_res);
944
945 if(cmdid)
946 IOleCommandTarget_Exec(&This->basedoc.IOleCommandTarget_iface, &CGID_MSHTML, cmdid, 0,
947 NULL, NULL);
948 }
949
950 void HTMLDocument_OleCmd_Init(HTMLDocument *This)
951 {
952 This->IOleCommandTarget_iface.lpVtbl = &OleCommandTargetVtbl;
953 }