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 #ifdef __REACTOS__ 245 // returning here fixes CORE-16884. Maybe use this until printing works. 246 ERR("Aborting print, to work around CORE-16884\n"); 247 nsIWebBrowserPrint_Release(nsprint); 248 return S_OK; 249 #endif 250 251 nsres = nsIWebBrowserPrint_GetGlobalPrintSettings(nsprint, &settings); 252 if(NS_FAILED(nsres)) 253 ERR("GetCurrentPrintSettings failed: %08x\n", nsres); 254 255 set_default_templates(settings); 256 257 if(pvaIn) { 258 switch(V_VT(pvaIn)) { 259 case VT_BYREF|VT_ARRAY: { 260 VARIANT *opts; 261 DWORD opts_cnt; 262 263 if(V_ARRAY(pvaIn)->cDims != 1) 264 WARN("cDims = %d\n", V_ARRAY(pvaIn)->cDims); 265 266 SafeArrayAccessData(V_ARRAY(pvaIn), (void**)&opts); 267 opts_cnt = V_ARRAY(pvaIn)->rgsabound[0].cElements; 268 269 if(opts_cnt >= 1) { 270 switch(V_VT(opts)) { 271 case VT_BSTR: 272 TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts))); 273 set_print_template(settings, V_BSTR(opts), TRUE); 274 break; 275 case VT_NULL: 276 break; 277 default: 278 WARN("opts = %s\n", debugstr_variant(opts)); 279 } 280 } 281 282 if(opts_cnt >= 2) { 283 switch(V_VT(opts+1)) { 284 case VT_BSTR: 285 TRACE("setting footer %s\n", debugstr_w(V_BSTR(opts+1))); 286 set_print_template(settings, V_BSTR(opts+1), FALSE); 287 break; 288 case VT_NULL: 289 break; 290 default: 291 WARN("opts[1] = %s\n", debugstr_variant(opts+1)); 292 } 293 } 294 295 if(opts_cnt >= 3) 296 FIXME("Unsupported opts_cnt %d\n", opts_cnt); 297 298 SafeArrayUnaccessData(V_ARRAY(pvaIn)); 299 break; 300 } 301 default: 302 FIXME("unsupported arg %s\n", debugstr_variant(pvaIn)); 303 } 304 } 305 306 nsres = nsIWebBrowserPrint_Print(nsprint, settings, NULL); 307 if(NS_FAILED(nsres)) 308 ERR("Print failed: %08x\n", nsres); 309 310 nsIWebBrowserPrint_Release(nsprint); 311 312 return S_OK; 313 } 314 315 static HRESULT exec_print_preview(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_page_setup(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_spell(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_properties(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_cut(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_copy(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 346 { 347 TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut); 348 349 do_ns_command(This, NSCMD_COPY, NULL); 350 return S_OK; 351 } 352 353 static HRESULT exec_paste(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 354 { 355 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 356 return E_NOTIMPL; 357 } 358 359 static HRESULT exec_paste_special(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 360 { 361 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 362 return E_NOTIMPL; 363 } 364 365 static HRESULT exec_undo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 366 { 367 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 368 return E_NOTIMPL; 369 } 370 371 static HRESULT exec_rendo(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 372 { 373 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 374 return E_NOTIMPL; 375 } 376 377 static HRESULT exec_select_all(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *in, VARIANT *out) 378 { 379 TRACE("(%p)\n", This); 380 381 if(in || out) 382 FIXME("unsupported args\n"); 383 384 if(This->doc_obj->nscontainer) 385 do_ns_command(This, NSCMD_SELECTALL, NULL); 386 387 update_doc(This, UPDATE_UI); 388 return S_OK; 389 } 390 391 static HRESULT exec_clear_selection(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 392 { 393 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 394 return E_NOTIMPL; 395 } 396 397 static HRESULT exec_zoom(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 398 { 399 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 400 return E_NOTIMPL; 401 } 402 403 static HRESULT exec_get_zoom_range(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 404 { 405 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 406 return E_NOTIMPL; 407 } 408 409 typedef struct { 410 task_t header; 411 HTMLOuterWindow *window; 412 }refresh_task_t; 413 414 static void refresh_proc(task_t *_task) 415 { 416 refresh_task_t *task = (refresh_task_t*)_task; 417 HTMLOuterWindow *window = task->window; 418 419 TRACE("%p\n", window); 420 421 window->readystate = READYSTATE_UNINITIALIZED; 422 423 if(window->doc_obj && window->doc_obj->client_cmdtrg) { 424 VARIANT var; 425 426 V_VT(&var) = VT_I4; 427 V_I4(&var) = 0; 428 IOleCommandTarget_Exec(window->doc_obj->client_cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL); 429 } 430 431 load_uri(task->window, task->window->uri, BINDING_REFRESH|BINDING_NOFRAG); 432 } 433 434 static void refresh_destr(task_t *_task) 435 { 436 refresh_task_t *task = (refresh_task_t*)_task; 437 438 IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface); 439 heap_free(task); 440 } 441 442 static HRESULT exec_refresh(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 443 { 444 refresh_task_t *task; 445 HRESULT hres; 446 447 TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut); 448 449 if(This->doc_obj->client) { 450 IOleCommandTarget *olecmd; 451 452 hres = IOleClientSite_QueryInterface(This->doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd); 453 if(SUCCEEDED(hres)) { 454 hres = IOleCommandTarget_Exec(olecmd, &CGID_DocHostCommandHandler, 2300, nCmdexecopt, pvaIn, pvaOut); 455 IOleCommandTarget_Release(olecmd); 456 if(SUCCEEDED(hres)) 457 return S_OK; 458 } 459 } 460 461 if(!This->window) 462 return E_UNEXPECTED; 463 464 task = heap_alloc(sizeof(*task)); 465 if(!task) 466 return E_OUTOFMEMORY; 467 468 IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface); 469 task->window = This->window; 470 471 return push_task(&task->header, refresh_proc, refresh_destr, This->window->task_magic); 472 } 473 474 static HRESULT exec_stop(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 475 { 476 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 477 return E_NOTIMPL; 478 } 479 480 static HRESULT exec_stop_download(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 481 { 482 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 483 return E_NOTIMPL; 484 } 485 486 static HRESULT exec_find(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 487 { 488 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 489 return E_NOTIMPL; 490 } 491 492 static HRESULT exec_delete(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 493 { 494 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 495 return E_NOTIMPL; 496 } 497 498 static HRESULT exec_enable_interaction(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 499 { 500 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 501 return E_NOTIMPL; 502 } 503 504 static HRESULT exec_on_unload(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 505 { 506 TRACE("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 507 508 /* Tests show that we have nothing more to do here */ 509 510 if(pvaOut) { 511 V_VT(pvaOut) = VT_BOOL; 512 V_BOOL(pvaOut) = VARIANT_TRUE; 513 } 514 515 return S_OK; 516 } 517 518 static HRESULT exec_show_page_setup(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 519 { 520 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 521 return E_NOTIMPL; 522 } 523 524 static HRESULT exec_show_print(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 525 { 526 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 527 return E_NOTIMPL; 528 } 529 530 static HRESULT exec_close(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 531 { 532 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 533 return E_NOTIMPL; 534 } 535 536 static HRESULT exec_set_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 537 { 538 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 539 return E_NOTIMPL; 540 } 541 542 static HRESULT exec_get_print_template(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 543 { 544 FIXME("(%p)->(%d %p %p)\n", This, nCmdexecopt, pvaIn, pvaOut); 545 return E_NOTIMPL; 546 } 547 548 static HRESULT exec_optical_zoom(HTMLDocument *This, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 549 { 550 TRACE("(%p)->(%d %s %p)\n", This, nCmdexecopt, debugstr_variant(pvaIn), pvaOut); 551 552 if(!pvaIn || V_VT(pvaIn) != VT_I4) { 553 FIXME("Unsupported argument %s\n", debugstr_variant(pvaIn)); 554 return E_NOTIMPL; 555 } 556 557 set_viewer_zoom(This->doc_obj->nscontainer, (float)V_I4(pvaIn)/100); 558 return S_OK; 559 } 560 561 static HRESULT query_mshtml_copy(HTMLDocument *This, OLECMD *cmd) 562 { 563 FIXME("(%p)\n", This); 564 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED; 565 return S_OK; 566 } 567 568 static HRESULT exec_mshtml_copy(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out) 569 { 570 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out); 571 572 if(This->doc_obj->usermode == EDITMODE) 573 return editor_exec_copy(This, cmdexecopt, in, out); 574 575 do_ns_command(This, NSCMD_COPY, NULL); 576 return S_OK; 577 } 578 579 static HRESULT query_mshtml_cut(HTMLDocument *This, OLECMD *cmd) 580 { 581 FIXME("(%p)\n", This); 582 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED; 583 return S_OK; 584 } 585 586 static HRESULT exec_mshtml_cut(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out) 587 { 588 nsIClipboardCommands *clipboard_commands; 589 nsresult nsres; 590 591 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out); 592 593 if(This->doc_obj->usermode == EDITMODE) 594 return editor_exec_cut(This, cmdexecopt, in, out); 595 596 clipboard_commands = get_clipboard_commands(This); 597 if(!clipboard_commands) 598 return E_UNEXPECTED; 599 600 nsres = nsIClipboardCommands_CutSelection(clipboard_commands); 601 nsIClipboardCommands_Release(clipboard_commands); 602 if(NS_FAILED(nsres)) { 603 ERR("Paste failed: %08x\n", nsres); 604 return E_FAIL; 605 } 606 607 return S_OK; 608 } 609 610 static HRESULT query_mshtml_paste(HTMLDocument *This, OLECMD *cmd) 611 { 612 FIXME("(%p)\n", This); 613 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED; 614 return S_OK; 615 } 616 617 static HRESULT exec_mshtml_paste(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out) 618 { 619 nsIClipboardCommands *clipboard_commands; 620 nsresult nsres; 621 622 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out); 623 624 if(This->doc_obj->usermode == EDITMODE) 625 return editor_exec_paste(This, cmdexecopt, in, out); 626 627 clipboard_commands = get_clipboard_commands(This); 628 if(!clipboard_commands) 629 return E_UNEXPECTED; 630 631 nsres = nsIClipboardCommands_Paste(clipboard_commands); 632 nsIClipboardCommands_Release(clipboard_commands); 633 if(NS_FAILED(nsres)) { 634 ERR("Paste failed: %08x\n", nsres); 635 return E_FAIL; 636 } 637 638 return S_OK; 639 } 640 641 static HRESULT query_selall_status(HTMLDocument *This, OLECMD *cmd) 642 { 643 TRACE("(%p)->(%p)\n", This, cmd); 644 645 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED; 646 return S_OK; 647 } 648 649 static HRESULT exec_browsemode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out) 650 { 651 WARN("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out); 652 653 if(in || out) 654 FIXME("unsupported args\n"); 655 656 This->doc_obj->usermode = BROWSEMODE; 657 658 return S_OK; 659 } 660 661 static HRESULT exec_editmode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out) 662 { 663 TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out); 664 665 if(in || out) 666 FIXME("unsupported args\n"); 667 668 return setup_edit_mode(This->doc_obj); 669 } 670 671 static HRESULT exec_htmleditmode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out) 672 { 673 FIXME("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out); 674 return S_OK; 675 } 676 677 static HRESULT exec_baselinefont3(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out) 678 { 679 FIXME("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out); 680 return S_OK; 681 } 682 683 static HRESULT exec_respectvisibility_indesign(HTMLDocument *This, DWORD cmdexecopt, 684 VARIANT *in, VARIANT *out) 685 { 686 TRACE("(%p)->(%x %s %p)\n", This, cmdexecopt, debugstr_variant(in), out); 687 688 /* This is turned on by default in Gecko. */ 689 if(!in || V_VT(in) != VT_BOOL || !V_BOOL(in)) 690 FIXME("Unsupported argument %s\n", debugstr_variant(in)); 691 692 return S_OK; 693 } 694 695 static HRESULT query_enabled_stub(HTMLDocument *This, OLECMD *cmd) 696 { 697 switch(cmd->cmdID) { 698 case IDM_PRINT: 699 FIXME("CGID_MSHTML: IDM_PRINT\n"); 700 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED; 701 break; 702 case IDM_BLOCKDIRLTR: 703 FIXME("CGID_MSHTML: IDM_BLOCKDIRLTR\n"); 704 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED; 705 break; 706 case IDM_BLOCKDIRRTL: 707 FIXME("CGID_MSHTML: IDM_BLOCKDIRRTL\n"); 708 cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED; 709 break; 710 } 711 712 return S_OK; 713 } 714 715 static const struct { 716 OLECMDF cmdf; 717 HRESULT (*func)(HTMLDocument*,DWORD,VARIANT*,VARIANT*); 718 } exec_table[] = { 719 {0}, 720 { OLECMDF_SUPPORTED, exec_open }, /* OLECMDID_OPEN */ 721 { OLECMDF_SUPPORTED, exec_new }, /* OLECMDID_NEW */ 722 { OLECMDF_SUPPORTED, exec_save }, /* OLECMDID_SAVE */ 723 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_save_as }, /* OLECMDID_SAVEAS */ 724 { OLECMDF_SUPPORTED, exec_save_copy_as }, /* OLECMDID_SAVECOPYAS */ 725 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_print }, /* OLECMDID_PRINT */ 726 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_print_preview }, /* OLECMDID_PRINTPREVIEW */ 727 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_page_setup }, /* OLECMDID_PAGESETUP */ 728 { OLECMDF_SUPPORTED, exec_spell }, /* OLECMDID_SPELL */ 729 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_properties }, /* OLECMDID_PROPERTIES */ 730 { OLECMDF_SUPPORTED, exec_cut }, /* OLECMDID_CUT */ 731 { OLECMDF_SUPPORTED, exec_copy }, /* OLECMDID_COPY */ 732 { OLECMDF_SUPPORTED, exec_paste }, /* OLECMDID_PASTE */ 733 { OLECMDF_SUPPORTED, exec_paste_special }, /* OLECMDID_PASTESPECIAL */ 734 { OLECMDF_SUPPORTED, exec_undo }, /* OLECMDID_UNDO */ 735 { OLECMDF_SUPPORTED, exec_rendo }, /* OLECMDID_REDO */ 736 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_select_all }, /* OLECMDID_SELECTALL */ 737 { OLECMDF_SUPPORTED, exec_clear_selection }, /* OLECMDID_CLEARSELECTION */ 738 { OLECMDF_SUPPORTED, exec_zoom }, /* OLECMDID_ZOOM */ 739 { OLECMDF_SUPPORTED, exec_get_zoom_range }, /* OLECMDID_GETZOOMRANGE */ 740 {0}, 741 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_refresh }, /* OLECMDID_REFRESH */ 742 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_stop }, /* OLECMDID_STOP */ 743 {0},{0},{0},{0},{0},{0}, 744 { OLECMDF_SUPPORTED, exec_stop_download }, /* OLECMDID_STOPDOWNLOAD */ 745 {0}, 746 { OLECMDF_SUPPORTED|OLECMDF_ENABLED, exec_find }, /* OLECMDID_FIND */ 747 { OLECMDF_SUPPORTED, exec_delete }, /* OLECMDID_DELETE */ 748 {0},{0}, 749 { OLECMDF_SUPPORTED, exec_enable_interaction }, /* OLECMDID_ENABLE_INTERACTION */ 750 { OLECMDF_SUPPORTED, exec_on_unload }, /* OLECMDID_ONUNLOAD */ 751 {0},{0},{0},{0},{0}, 752 { OLECMDF_SUPPORTED, exec_show_page_setup }, /* OLECMDID_SHOWPAGESETUP */ 753 { OLECMDF_SUPPORTED, exec_show_print }, /* OLECMDID_SHOWPRINT */ 754 {0},{0}, 755 { OLECMDF_SUPPORTED, exec_close }, /* OLECMDID_CLOSE */ 756 {0},{0},{0}, 757 { OLECMDF_SUPPORTED, exec_set_print_template }, /* OLECMDID_SETPRINTTEMPLATE */ 758 { OLECMDF_SUPPORTED, exec_get_print_template }, /* OLECMDID_GETPRINTTEMPLATE */ 759 {0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, 760 { 0, /* not reported as supported */ exec_optical_zoom } /* OLECMDID_OPTICAL_ZOOM */ 761 }; 762 763 static const cmdtable_t base_cmds[] = { 764 {IDM_COPY, query_mshtml_copy, exec_mshtml_copy}, 765 {IDM_PASTE, query_mshtml_paste, exec_mshtml_paste}, 766 {IDM_CUT, query_mshtml_cut, exec_mshtml_cut}, 767 {IDM_SELECTALL, query_selall_status, exec_select_all}, 768 {IDM_BROWSEMODE, NULL, exec_browsemode}, 769 {IDM_EDITMODE, NULL, exec_editmode}, 770 {IDM_PRINT, query_enabled_stub, exec_print}, 771 {IDM_HTMLEDITMODE, NULL, exec_htmleditmode}, 772 {IDM_BASELINEFONT3, NULL, exec_baselinefont3}, 773 {IDM_BLOCKDIRLTR, query_enabled_stub, NULL}, 774 {IDM_BLOCKDIRRTL, query_enabled_stub, NULL}, 775 {IDM_RESPECTVISIBILITY_INDESIGN, NULL, exec_respectvisibility_indesign}, 776 {0,NULL,NULL} 777 }; 778 779 static HRESULT WINAPI OleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv) 780 { 781 HTMLDocument *This = impl_from_IOleCommandTarget(iface); 782 return htmldoc_query_interface(This, riid, ppv); 783 } 784 785 static ULONG WINAPI OleCommandTarget_AddRef(IOleCommandTarget *iface) 786 { 787 HTMLDocument *This = impl_from_IOleCommandTarget(iface); 788 return htmldoc_addref(This); 789 } 790 791 static ULONG WINAPI OleCommandTarget_Release(IOleCommandTarget *iface) 792 { 793 HTMLDocument *This = impl_from_IOleCommandTarget(iface); 794 return htmldoc_release(This); 795 } 796 797 static HRESULT query_from_table(HTMLDocument *This, const cmdtable_t *cmdtable, OLECMD *cmd) 798 { 799 const cmdtable_t *iter = cmdtable; 800 801 cmd->cmdf = 0; 802 803 while(iter->id && iter->id != cmd->cmdID) 804 iter++; 805 806 if(!iter->id || !iter->query) 807 return OLECMDERR_E_NOTSUPPORTED; 808 809 return iter->query(This, cmd); 810 } 811 812 static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup, 813 ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText) 814 { 815 HTMLDocument *This = impl_from_IOleCommandTarget(iface); 816 HRESULT hres; 817 818 TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText); 819 820 if(pCmdText) 821 FIXME("Unsupported pCmdText\n"); 822 if(!cCmds) 823 return S_OK; 824 825 if(!pguidCmdGroup) { 826 ULONG i; 827 828 for(i=0; i<cCmds; i++) { 829 if(prgCmds[i].cmdID < OLECMDID_OPEN || prgCmds[i].cmdID >= sizeof(exec_table)/sizeof(*exec_table)) { 830 WARN("Unsupported cmdID = %d\n", prgCmds[i].cmdID); 831 prgCmds[i].cmdf = 0; 832 }else { 833 if(prgCmds[i].cmdID == OLECMDID_OPEN || prgCmds[i].cmdID == OLECMDID_NEW) { 834 IOleCommandTarget *cmdtrg = NULL; 835 OLECMD olecmd; 836 837 prgCmds[i].cmdf = OLECMDF_SUPPORTED; 838 if(This->doc_obj->client) { 839 hres = IOleClientSite_QueryInterface(This->doc_obj->client, &IID_IOleCommandTarget, 840 (void**)&cmdtrg); 841 if(SUCCEEDED(hres)) { 842 olecmd.cmdID = prgCmds[i].cmdID; 843 olecmd.cmdf = 0; 844 845 hres = IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &olecmd, NULL); 846 if(SUCCEEDED(hres) && olecmd.cmdf) 847 prgCmds[i].cmdf = olecmd.cmdf; 848 } 849 }else { 850 ERR("This->client == NULL, native would crash\n"); 851 } 852 }else { 853 prgCmds[i].cmdf = exec_table[prgCmds[i].cmdID].cmdf; 854 TRACE("cmdID = %d returning %x\n", prgCmds[i].cmdID, prgCmds[i].cmdf); 855 } 856 } 857 } 858 859 return (prgCmds[cCmds-1].cmdf & OLECMDF_SUPPORTED) ? S_OK : OLECMDERR_E_NOTSUPPORTED; 860 } 861 862 if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) { 863 ULONG i; 864 865 for(i=0; i<cCmds; i++) { 866 hres = query_from_table(This, base_cmds, prgCmds+i); 867 if(hres == OLECMDERR_E_NOTSUPPORTED) 868 hres = query_from_table(This, editmode_cmds, prgCmds+i); 869 if(hres == OLECMDERR_E_NOTSUPPORTED) 870 FIXME("CGID_MSHTML: unsupported cmdID %d\n", prgCmds[i].cmdID); 871 } 872 873 return (prgCmds[cCmds-1].cmdf & OLECMDF_SUPPORTED) ? S_OK : OLECMDERR_E_NOTSUPPORTED; 874 } 875 876 FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup)); 877 return OLECMDERR_E_UNKNOWNGROUP; 878 } 879 880 static HRESULT exec_from_table(HTMLDocument *This, const cmdtable_t *cmdtable, DWORD cmdid, 881 DWORD cmdexecopt, VARIANT *in, VARIANT *out) 882 { 883 const cmdtable_t *iter = cmdtable; 884 885 while(iter->id && iter->id != cmdid) 886 iter++; 887 888 if(!iter->id || !iter->exec) 889 return OLECMDERR_E_NOTSUPPORTED; 890 891 return iter->exec(This, cmdexecopt, in, out); 892 } 893 894 static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup, 895 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 896 { 897 HTMLDocument *This = impl_from_IOleCommandTarget(iface); 898 899 if(!pguidCmdGroup) { 900 if(nCmdID < OLECMDID_OPEN || nCmdID >= sizeof(exec_table)/sizeof(*exec_table) || !exec_table[nCmdID].func) { 901 WARN("Unsupported cmdID = %d\n", nCmdID); 902 return OLECMDERR_E_NOTSUPPORTED; 903 } 904 905 return exec_table[nCmdID].func(This, nCmdexecopt, pvaIn, pvaOut); 906 }else if(IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) { 907 FIXME("unsupported nCmdID %d of CGID_Explorer group\n", nCmdID); 908 TRACE("%p %p\n", pvaIn, pvaOut); 909 return OLECMDERR_E_NOTSUPPORTED; 910 }else if(IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup)) { 911 FIXME("unsupported nCmdID %d of CGID_ShellDocView group\n", nCmdID); 912 return OLECMDERR_E_NOTSUPPORTED; 913 }else if(IsEqualGUID(&CGID_MSHTML, pguidCmdGroup)) { 914 HRESULT hres = exec_from_table(This, base_cmds, nCmdID, nCmdexecopt, pvaIn, pvaOut); 915 if(hres == OLECMDERR_E_NOTSUPPORTED) 916 hres = exec_from_table(This, editmode_cmds, nCmdID, 917 nCmdexecopt, pvaIn, pvaOut); 918 if(hres == OLECMDERR_E_NOTSUPPORTED) 919 FIXME("unsupported nCmdID %d of CGID_MSHTML group\n", nCmdID); 920 921 return hres; 922 } 923 924 FIXME("Unsupported pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup)); 925 return OLECMDERR_E_UNKNOWNGROUP; 926 } 927 928 static const IOleCommandTargetVtbl OleCommandTargetVtbl = { 929 OleCommandTarget_QueryInterface, 930 OleCommandTarget_AddRef, 931 OleCommandTarget_Release, 932 OleCommandTarget_QueryStatus, 933 OleCommandTarget_Exec 934 }; 935 936 void show_context_menu(HTMLDocumentObj *This, DWORD dwID, POINT *ppt, IDispatch *elem) 937 { 938 HMENU menu_res, menu; 939 DWORD cmdid; 940 941 if(This->hostui && S_OK == IDocHostUIHandler_ShowContextMenu(This->hostui, 942 dwID, ppt, (IUnknown*)&This->basedoc.IOleCommandTarget_iface, elem)) 943 return; 944 945 menu_res = LoadMenuW(get_shdoclc(), MAKEINTRESOURCEW(IDR_BROWSE_CONTEXT_MENU)); 946 menu = GetSubMenu(menu_res, dwID); 947 948 cmdid = TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, 949 ppt->x, ppt->y, 0, This->hwnd, NULL); 950 DestroyMenu(menu_res); 951 952 if(cmdid) 953 IOleCommandTarget_Exec(&This->basedoc.IOleCommandTarget_iface, &CGID_MSHTML, cmdid, 0, 954 NULL, NULL); 955 } 956 957 void HTMLDocument_OleCmd_Init(HTMLDocument *This) 958 { 959 This->IOleCommandTarget_iface.lpVtbl = &OleCommandTargetVtbl; 960 } 961