winex11: Abstract window map/unmap to separate functions.
[wine] / dlls / shdocvw / dochost.c
1 /*
2  * Copyright 2005-2006 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "wine/debug.h"
20 #include "shdocvw.h"
21 #include "hlink.h"
22 #include "exdispid.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
25
26 static ATOM doc_view_atom = 0;
27
28 void push_dochost_task(DocHost *This, task_header_t *task, task_proc_t proc, BOOL send)
29 {
30     task->proc = proc;
31
32     /* FIXME: Don't use lParam */
33     if(send)
34         SendMessageW(This->frame_hwnd, WM_DOCHOSTTASK, 0, (LPARAM)task);
35     else
36         PostMessageW(This->frame_hwnd, WM_DOCHOSTTASK, 0, (LPARAM)task);
37 }
38
39 LRESULT process_dochost_task(DocHost *This, LPARAM lparam)
40 {
41     task_header_t *task = (task_header_t*)lparam;
42
43     task->proc(This, task);
44
45     heap_free(task);
46     return 0;
47 }
48
49 static void navigate_complete(DocHost *This)
50 {
51     IDispatch *disp = NULL;
52     DISPPARAMS dispparams;
53     VARIANTARG params[2];
54     VARIANT url;
55     HRESULT hres;
56
57     hres = IUnknown_QueryInterface(This->document, &IID_IDispatch, (void**)&disp);
58     if(FAILED(hres))
59         FIXME("Could not get IDispatch interface\n");
60
61     dispparams.cArgs = 2;
62     dispparams.cNamedArgs = 0;
63     dispparams.rgdispidNamedArgs = NULL;
64     dispparams.rgvarg = params;
65
66     V_VT(params) = (VT_BYREF|VT_VARIANT);
67     V_BYREF(params) = &url;
68
69     V_VT(params+1) = VT_DISPATCH;
70     V_DISPATCH(params+1) = disp;
71
72     V_VT(&url) = VT_BSTR;
73     V_BSTR(&url) = SysAllocString(This->url);
74
75     call_sink(This->cps.wbe2, DISPID_NAVIGATECOMPLETE2, &dispparams);
76     call_sink(This->cps.wbe2, DISPID_DOCUMENTCOMPLETE, &dispparams);
77
78     SysFreeString(V_BSTR(&url));
79     if(disp)
80         IDispatch_Release(disp);
81     This->busy = VARIANT_FALSE;
82 }
83
84 void object_available(DocHost *This)
85 {
86     IHlinkTarget *hlink;
87     HRESULT hres;
88
89     TRACE("(%p)\n", This);
90
91     if(!This->document) {
92         WARN("document == NULL\n");
93         return;
94     }
95
96     hres = IUnknown_QueryInterface(This->document, &IID_IHlinkTarget, (void**)&hlink);
97     if(FAILED(hres)) {
98         FIXME("Could not get IHlinkTarget interface\n");
99         return;
100     }
101
102     hres = IHlinkTarget_Navigate(hlink, 0, NULL);
103     IHlinkTarget_Release(hlink);
104     if(FAILED(hres)) {
105         FIXME("Navigate failed\n");
106         return;
107     }
108
109     navigate_complete(This);
110
111     return;
112 }
113
114 static LRESULT resize_document(DocHost *This, LONG width, LONG height)
115 {
116     RECT rect = {0, 0, width, height};
117
118     TRACE("(%p)->(%d %d)\n", This, width, height);
119
120     if(This->view)
121         IOleDocumentView_SetRect(This->view, &rect);
122
123     return 0;
124 }
125
126 static LRESULT WINAPI doc_view_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
127 {
128     DocHost *This;
129
130     static const WCHAR wszTHIS[] = {'T','H','I','S',0};
131
132     if(msg == WM_CREATE) {
133         This = *(DocHost**)lParam;
134         SetPropW(hwnd, wszTHIS, This);
135     }else {
136         This = GetPropW(hwnd, wszTHIS);
137     }
138
139     switch(msg) {
140     case WM_SIZE:
141         return resize_document(This, LOWORD(lParam), HIWORD(lParam));
142     }
143
144     return DefWindowProcW(hwnd, msg, wParam, lParam);
145 }
146
147 void create_doc_view_hwnd(DocHost *This)
148 {
149     RECT rect;
150
151     static const WCHAR wszShell_DocObject_View[] =
152         {'S','h','e','l','l',' ','D','o','c','O','b','j','e','c','t',' ','V','i','e','w',0};
153
154     if(!doc_view_atom) {
155         static WNDCLASSEXW wndclass = {
156             sizeof(wndclass),
157             CS_PARENTDC,
158             doc_view_proc,
159             0, 0 /* native uses 4*/, NULL, NULL, NULL,
160             (HBRUSH)COLOR_WINDOWFRAME, NULL,
161             wszShell_DocObject_View,
162             NULL
163         };
164
165         wndclass.hInstance = shdocvw_hinstance;
166
167         doc_view_atom = RegisterClassExW(&wndclass);
168     }
169
170     GetClientRect(This->frame_hwnd, &rect); /* FIXME */
171     This->hwnd = CreateWindowExW(0, wszShell_DocObject_View,
172          wszShell_DocObject_View,
173          WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP,
174          rect.left, rect.top, rect.right, rect.bottom, This->frame_hwnd,
175          NULL, shdocvw_hinstance, This);
176 }
177
178 void deactivate_document(DocHost *This)
179 {
180     IOleInPlaceObjectWindowless *winobj;
181     IOleObject *oleobj = NULL;
182     IHlinkTarget *hlink = NULL;
183     HRESULT hres;
184
185     if(This->view)
186         IOleDocumentView_UIActivate(This->view, FALSE);
187
188     hres = IUnknown_QueryInterface(This->document, &IID_IOleInPlaceObjectWindowless,
189                                    (void**)&winobj);
190     if(SUCCEEDED(hres)) {
191         IOleInPlaceObjectWindowless_InPlaceDeactivate(winobj);
192         IOleInPlaceObjectWindowless_Release(winobj);
193     }
194
195     if(This->view) {
196         IOleDocumentView_Show(This->view, FALSE);
197         IOleDocumentView_CloseView(This->view, 0);
198         IOleDocumentView_SetInPlaceSite(This->view, NULL);
199         IOleDocumentView_Release(This->view);
200         This->view = NULL;
201     }
202
203     hres = IUnknown_QueryInterface(This->document, &IID_IOleObject, (void**)&oleobj);
204     if(SUCCEEDED(hres))
205         IOleObject_Close(oleobj, OLECLOSE_NOSAVE);
206
207     hres = IUnknown_QueryInterface(This->document, &IID_IHlinkTarget, (void**)&hlink);
208     if(SUCCEEDED(hres)) {
209         IHlinkTarget_SetBrowseContext(hlink, NULL);
210         IHlinkTarget_Release(hlink);
211     }
212
213     if(oleobj) {
214         IOleClientSite *client_site = NULL;
215
216         IOleObject_GetClientSite(oleobj, &client_site);
217         if(client_site) {
218             if(client_site == CLIENTSITE(This))
219                 IOleObject_SetClientSite(oleobj, NULL);
220             IOleClientSite_Release(client_site);
221         }
222
223         IOleObject_Release(oleobj);
224     }
225
226     IUnknown_Release(This->document);
227     This->document = NULL;
228 }
229
230 #define OLECMD_THIS(iface) DEFINE_THIS(DocHost, OleCommandTarget, iface)
231
232 static HRESULT WINAPI ClOleCommandTarget_QueryInterface(IOleCommandTarget *iface,
233         REFIID riid, void **ppv)
234 {
235     DocHost *This = OLECMD_THIS(iface);
236     return IOleClientSite_QueryInterface(CLIENTSITE(This), riid, ppv);
237 }
238
239 static ULONG WINAPI ClOleCommandTarget_AddRef(IOleCommandTarget *iface)
240 {
241     DocHost *This = OLECMD_THIS(iface);
242     return IOleClientSite_AddRef(CLIENTSITE(This));
243 }
244
245 static ULONG WINAPI ClOleCommandTarget_Release(IOleCommandTarget *iface)
246 {
247     DocHost *This = OLECMD_THIS(iface);
248     return IOleClientSite_Release(CLIENTSITE(This));
249 }
250
251 static HRESULT WINAPI ClOleCommandTarget_QueryStatus(IOleCommandTarget *iface,
252         const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
253 {
254     DocHost *This = OLECMD_THIS(iface);
255     FIXME("(%p)->(%s %u %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds,
256           pCmdText);
257     return E_NOTIMPL;
258 }
259
260 static HRESULT WINAPI ClOleCommandTarget_Exec(IOleCommandTarget *iface,
261         const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn,
262         VARIANT *pvaOut)
263 {
264     DocHost *This = OLECMD_THIS(iface);
265     FIXME("(%p)->(%s %d %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID,
266           nCmdexecopt, pvaIn, pvaOut);
267     return E_NOTIMPL;
268 }
269
270 #undef OLECMD_THIS
271
272 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
273     ClOleCommandTarget_QueryInterface,
274     ClOleCommandTarget_AddRef,
275     ClOleCommandTarget_Release,
276     ClOleCommandTarget_QueryStatus,
277     ClOleCommandTarget_Exec
278 };
279
280 #define DOCHOSTUI_THIS(iface) DEFINE_THIS(DocHost, DocHostUIHandler, iface)
281
282 static HRESULT WINAPI DocHostUIHandler_QueryInterface(IDocHostUIHandler2 *iface,
283                                                       REFIID riid, void **ppv)
284 {
285     DocHost *This = DOCHOSTUI_THIS(iface);
286     return IOleClientSite_QueryInterface(CLIENTSITE(This), riid, ppv);
287 }
288
289 static ULONG WINAPI DocHostUIHandler_AddRef(IDocHostUIHandler2 *iface)
290 {
291     DocHost *This = DOCHOSTUI_THIS(iface);
292     return IOleClientSite_AddRef(CLIENTSITE(This));
293 }
294
295 static ULONG WINAPI DocHostUIHandler_Release(IDocHostUIHandler2 *iface)
296 {
297     DocHost *This = DOCHOSTUI_THIS(iface);
298     return IOleClientSite_Release(CLIENTSITE(This));
299 }
300
301 static HRESULT WINAPI DocHostUIHandler_ShowContextMenu(IDocHostUIHandler2 *iface,
302          DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
303 {
304     DocHost *This = DOCHOSTUI_THIS(iface);
305     HRESULT hres;
306
307     TRACE("(%p)->(%d %p %p %p)\n", This, dwID, ppt, pcmdtReserved, pdispReserved);
308
309     if(This->hostui) {
310         hres = IDocHostUIHandler_ShowContextMenu(This->hostui, dwID, ppt, pcmdtReserved,
311                                                  pdispReserved);
312         if(hres == S_OK)
313             return S_OK;
314     }
315
316     FIXME("default action not implemented\n");
317     return E_NOTIMPL;
318 }
319
320 static HRESULT WINAPI DocHostUIHandler_GetHostInfo(IDocHostUIHandler2 *iface,
321         DOCHOSTUIINFO *pInfo)
322 {
323     DocHost *This = DOCHOSTUI_THIS(iface);
324     HRESULT hres;
325
326     TRACE("(%p)->(%p)\n", This, pInfo);
327
328     if(This->hostui) {
329         hres = IDocHostUIHandler_GetHostInfo(This->hostui, pInfo);
330         if(SUCCEEDED(hres))
331             return hres;
332     }
333
334     pInfo->dwFlags = DOCHOSTUIFLAG_DISABLE_HELP_MENU | DOCHOSTUIFLAG_OPENNEWWIN
335         | DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8 | DOCHOSTUIFLAG_ENABLE_INPLACE_NAVIGATION
336         | DOCHOSTUIFLAG_IME_ENABLE_RECONVERSION;
337     return S_OK;
338 }
339
340 static HRESULT WINAPI DocHostUIHandler_ShowUI(IDocHostUIHandler2 *iface, DWORD dwID,
341         IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget,
342         IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc)
343 {
344     DocHost *This = DOCHOSTUI_THIS(iface);
345     FIXME("(%p)->(%d %p %p %p %p)\n", This, dwID, pActiveObject, pCommandTarget,
346           pFrame, pDoc);
347     return E_NOTIMPL;
348 }
349
350 static HRESULT WINAPI DocHostUIHandler_HideUI(IDocHostUIHandler2 *iface)
351 {
352     DocHost *This = DOCHOSTUI_THIS(iface);
353     FIXME("(%p)\n", This);
354     return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI DocHostUIHandler_UpdateUI(IDocHostUIHandler2 *iface)
358 {
359     DocHost *This = DOCHOSTUI_THIS(iface);
360
361     TRACE("(%p)\n", This);
362
363     if(!This->hostui)
364         return S_FALSE;
365
366     return IDocHostUIHandler_UpdateUI(This->hostui);
367 }
368
369 static HRESULT WINAPI DocHostUIHandler_EnableModeless(IDocHostUIHandler2 *iface,
370                                                       BOOL fEnable)
371 {
372     DocHost *This = DOCHOSTUI_THIS(iface);
373     FIXME("(%p)->(%x)\n", This, fEnable);
374     return E_NOTIMPL;
375 }
376
377 static HRESULT WINAPI DocHostUIHandler_OnDocWindowActivate(IDocHostUIHandler2 *iface,
378                                                            BOOL fActivate)
379 {
380     DocHost *This = DOCHOSTUI_THIS(iface);
381     FIXME("(%p)->(%x)\n", This, fActivate);
382     return E_NOTIMPL;
383 }
384
385 static HRESULT WINAPI DocHostUIHandler_OnFrameWindowActivate(IDocHostUIHandler2 *iface,
386                                                              BOOL fActivate)
387 {
388     DocHost *This = DOCHOSTUI_THIS(iface);
389     FIXME("(%p)->(%x)\n", This, fActivate);
390     return E_NOTIMPL;
391 }
392
393 static HRESULT WINAPI DocHostUIHandler_ResizeBorder(IDocHostUIHandler2 *iface,
394         LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
395 {
396     DocHost *This = DOCHOSTUI_THIS(iface);
397     FIXME("(%p)->(%p %p %X)\n", This, prcBorder, pUIWindow, fRameWindow);
398     return E_NOTIMPL;
399 }
400
401 static HRESULT WINAPI DocHostUIHandler_TranslateAccelerator(IDocHostUIHandler2 *iface,
402         LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
403 {
404     DocHost *This = DOCHOSTUI_THIS(iface);
405     FIXME("(%p)->(%p %p %d)\n", This, lpMsg, pguidCmdGroup, nCmdID);
406     return E_NOTIMPL;
407 }
408
409 static HRESULT WINAPI DocHostUIHandler_GetOptionKeyPath(IDocHostUIHandler2 *iface,
410         LPOLESTR *pchKey, DWORD dw)
411 {
412     DocHost *This = DOCHOSTUI_THIS(iface);
413
414     TRACE("(%p)->(%p %d)\n", This, pchKey, dw);
415
416     if(This->hostui)
417         return IDocHostUIHandler_GetOptionKeyPath(This->hostui, pchKey, dw);
418
419     return S_OK;
420 }
421
422 static HRESULT WINAPI DocHostUIHandler_GetDropTarget(IDocHostUIHandler2 *iface,
423         IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
424 {
425     DocHost *This = DOCHOSTUI_THIS(iface);
426     FIXME("(%p)\n", This);
427     return E_NOTIMPL;
428 }
429
430 static HRESULT WINAPI DocHostUIHandler_GetExternal(IDocHostUIHandler2 *iface,
431         IDispatch **ppDispatch)
432 {
433     DocHost *This = DOCHOSTUI_THIS(iface);
434
435     TRACE("(%p)->(%p)\n", This, ppDispatch);
436
437     if(This->hostui)
438         return IDocHostUIHandler_GetExternal(This->hostui, ppDispatch);
439
440     FIXME("default action not implemented\n");
441     return E_NOTIMPL;
442 }
443
444 static HRESULT WINAPI DocHostUIHandler_TranslateUrl(IDocHostUIHandler2 *iface,
445         DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
446 {
447     DocHost *This = DOCHOSTUI_THIS(iface);
448
449     TRACE("(%p)->(%d %s %p)\n", This, dwTranslate, debugstr_w(pchURLIn), ppchURLOut);
450
451     if(This->hostui)
452         return IDocHostUIHandler_TranslateUrl(This->hostui, dwTranslate,
453                                               pchURLIn, ppchURLOut);
454
455     return S_FALSE;
456 }
457
458 static HRESULT WINAPI DocHostUIHandler_FilterDataObject(IDocHostUIHandler2 *iface,
459         IDataObject *pDO, IDataObject **ppDORet)
460 {
461     DocHost *This = DOCHOSTUI_THIS(iface);
462     FIXME("(%p)->(%p %p)\n", This, pDO, ppDORet);
463     return E_NOTIMPL;
464 }
465
466 static HRESULT WINAPI DocHostUIHandler_GetOverrideKeyPath(IDocHostUIHandler2 *iface,
467         LPOLESTR *pchKey, DWORD dw)
468 {
469     DocHost *This = DOCHOSTUI_THIS(iface);
470     IDocHostUIHandler2 *handler;
471     HRESULT hres;
472
473     TRACE("(%p)->(%p %d)\n", This, pchKey, dw);
474
475     if(!This->hostui)
476         return S_OK;
477
478     hres = IDocHostUIHandler_QueryInterface(This->hostui, &IID_IDocHostUIHandler2,
479                                             (void**)&handler);
480     if(SUCCEEDED(hres)) {
481         hres = IDocHostUIHandler2_GetOverrideKeyPath(handler, pchKey, dw);
482         IDocHostUIHandler2_Release(handler);
483         return hres;
484     }
485
486     return S_OK;
487 }
488
489 #undef DOCHOSTUI_THIS
490
491 static const IDocHostUIHandler2Vtbl DocHostUIHandler2Vtbl = {
492     DocHostUIHandler_QueryInterface,
493     DocHostUIHandler_AddRef,
494     DocHostUIHandler_Release,
495     DocHostUIHandler_ShowContextMenu,
496     DocHostUIHandler_GetHostInfo,
497     DocHostUIHandler_ShowUI,
498     DocHostUIHandler_HideUI,
499     DocHostUIHandler_UpdateUI,
500     DocHostUIHandler_EnableModeless,
501     DocHostUIHandler_OnDocWindowActivate,
502     DocHostUIHandler_OnFrameWindowActivate,
503     DocHostUIHandler_ResizeBorder,
504     DocHostUIHandler_TranslateAccelerator,
505     DocHostUIHandler_GetOptionKeyPath,
506     DocHostUIHandler_GetDropTarget,
507     DocHostUIHandler_GetExternal,
508     DocHostUIHandler_TranslateUrl,
509     DocHostUIHandler_FilterDataObject,
510     DocHostUIHandler_GetOverrideKeyPath
511 };
512
513 void DocHost_Init(DocHost *This, IDispatch *disp)
514 {
515     This->lpDocHostUIHandlerVtbl = &DocHostUIHandler2Vtbl;
516     This->lpOleCommandTargetVtbl = &OleCommandTargetVtbl;
517
518     This->disp = disp;
519
520     This->client_disp = NULL;
521
522     This->document = NULL;
523     This->hostui = NULL;
524     This->frame = NULL;
525
526     This->hwnd = NULL;
527     This->frame_hwnd = NULL;
528     This->url = NULL;
529
530     This->silent = VARIANT_FALSE;
531     This->offline = VARIANT_FALSE;
532
533     DocHost_ClientSite_Init(This);
534     DocHost_Frame_Init(This);
535
536     ConnectionPointContainer_Init(&This->cps, (IUnknown*)disp);
537 }
538
539 void DocHost_Release(DocHost *This)
540 {
541     if(This->client_disp)
542         IDispatch_Release(This->client_disp);
543     if(This->frame)
544         IOleInPlaceFrame_Release(This->frame);
545
546     DocHost_ClientSite_Release(This);
547
548     ConnectionPointContainer_Destroy(&This->cps);
549
550     SysFreeString(This->url);
551 }