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 } 954