Fix protocol test on winxp.
[wine] / dlls / mshtml / view.c
1 /*
2  * Copyright 2005 Jacek Caban
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "wingdi.h"
30 #include "ole2.h"
31
32 #include "wine/debug.h"
33
34 #include "mshtml_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 static const WCHAR wszInternetExplorer_Server[] =
39     {'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','_','S','e','r','v','e','r',0};
40 static const WCHAR wszHTML_Document[] =
41     {'H','T','M','L',' ','D','o','c','u','m','e','n','t',0};
42
43 static ATOM serverwnd_class = 0;
44
45 static void paint_disabled(HWND hwnd) {
46     HDC hdc;
47     PAINTSTRUCT ps;
48     HBRUSH brush;
49     RECT rect;
50     HFONT font;
51
52     font = CreateFontA(25,0,0,0,400,0,0,0,ANSI_CHARSET,0,0,DEFAULT_QUALITY,DEFAULT_PITCH,NULL);
53     brush = CreateSolidBrush(RGB(255,255,255));
54     GetClientRect(hwnd, &rect);
55
56     hdc = BeginPaint(hwnd, &ps);
57     SelectObject(hdc, font);
58     SelectObject(hdc, brush);
59     Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
60     DrawTextA(hdc, "HTML rendering is currently disabled.",-1, &rect,
61             DT_CENTER | DT_SINGLELINE | DT_VCENTER);
62     EndPaint(hwnd, &ps);
63
64     DeleteObject(font);
65     DeleteObject(brush);
66 }
67
68 static void activate_gecko(HTMLDocument *This)
69 {
70     TRACE("(%p) %p\n", This, This->nscontainer->window);
71
72     SetParent(This->nscontainer->hwnd, This->hwnd);
73     ShowWindow(This->nscontainer->hwnd, SW_SHOW);
74
75     nsIBaseWindow_SetVisibility(This->nscontainer->window, TRUE);
76     nsIBaseWindow_SetEnabled(This->nscontainer->window, TRUE);
77 }
78
79 static LRESULT WINAPI serverwnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
80 {
81     HTMLDocument *This;
82
83     static const WCHAR wszTHIS[] = {'T','H','I','S',0};
84
85     if(msg == WM_CREATE) {
86         This = *(HTMLDocument**)lParam;
87         SetPropW(hwnd, wszTHIS, This);
88     }else {
89         This = (HTMLDocument*)GetPropW(hwnd, wszTHIS);
90     }
91
92     switch(msg) {
93     case WM_CREATE:
94         This->hwnd = hwnd;
95         if(This->nscontainer)
96             activate_gecko(This);
97         break;
98     case WM_PAINT:
99         if(!This->nscontainer)
100             paint_disabled(hwnd);
101         break;
102     case WM_SIZE:
103         TRACE("(%p)->(WM_SIZE)\n", This);
104         if(This->nscontainer)
105             SetWindowPos(This->nscontainer->hwnd, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam),
106                     SWP_NOZORDER | SWP_NOACTIVATE);
107     }
108         
109     return DefWindowProcW(hwnd, msg, wParam, lParam);
110 }
111
112 static void register_serverwnd_class(void)
113 {
114     static WNDCLASSEXW wndclass = {
115         sizeof(WNDCLASSEXW),
116         CS_DBLCLKS,
117         serverwnd_proc,
118         0, 0, NULL, NULL, NULL, NULL, NULL,
119         wszInternetExplorer_Server,
120         NULL,
121     };
122     wndclass.hInstance = hInst;
123     serverwnd_class = RegisterClassExW(&wndclass);
124 }
125
126 /**********************************************************
127  * IOleDocumentView implementation
128  */
129
130 #define DOCVIEW_THIS(iface) DEFINE_THIS(HTMLDocument, OleDocumentView, iface)
131
132 static HRESULT WINAPI OleDocumentView_QueryInterface(IOleDocumentView *iface, REFIID riid, void **ppvObject)
133 {
134     HTMLDocument *This = DOCVIEW_THIS(iface);
135     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
136 }
137
138 static ULONG WINAPI OleDocumentView_AddRef(IOleDocumentView *iface)
139 {
140     HTMLDocument *This = DOCVIEW_THIS(iface);
141     return IHTMLDocument2_AddRef(HTMLDOC(This));
142 }
143
144 static ULONG WINAPI OleDocumentView_Release(IOleDocumentView *iface)
145 {
146     HTMLDocument *This = DOCVIEW_THIS(iface);
147     return IHTMLDocument2_Release(HTMLDOC(This));
148 }
149
150 static HRESULT WINAPI OleDocumentView_SetInPlaceSite(IOleDocumentView *iface, IOleInPlaceSite *pIPSite)
151 {
152     HTMLDocument *This = DOCVIEW_THIS(iface);
153     TRACE("(%p)->(%p)\n", This, pIPSite);
154
155     if(pIPSite)
156         IOleInPlaceSite_AddRef(pIPSite);
157
158     if(This->ipsite)
159         IOleInPlaceSite_Release(This->ipsite);
160
161     This->ipsite = pIPSite;
162     return S_OK;
163 }
164
165 static HRESULT WINAPI OleDocumentView_GetInPlaceSite(IOleDocumentView *iface, IOleInPlaceSite **ppIPSite)
166 {
167     HTMLDocument *This = DOCVIEW_THIS(iface);
168     TRACE("(%p)->(%p)\n", This, ppIPSite);
169
170     if(!ppIPSite)
171         return E_INVALIDARG;
172
173     if(This->ipsite)
174         IOleInPlaceSite_AddRef(This->ipsite);
175
176     *ppIPSite = This->ipsite;
177     return S_OK;
178 }
179
180 static HRESULT WINAPI OleDocumentView_GetDocument(IOleDocumentView *iface, IUnknown **ppunk)
181 {
182     HTMLDocument *This = DOCVIEW_THIS(iface);
183     TRACE("(%p)->(%p)\n", This, ppunk);
184
185     if(!ppunk)
186         return E_INVALIDARG;
187
188     IHTMLDocument2_AddRef(HTMLDOC(This));
189     *ppunk = (IUnknown*)HTMLDOC(This);
190     return S_OK;
191 }
192
193 static HRESULT WINAPI OleDocumentView_SetRect(IOleDocumentView *iface, LPRECT prcView)
194 {
195     HTMLDocument *This = DOCVIEW_THIS(iface);
196     RECT rect;
197
198     TRACE("(%p)->(%p)\n", This, prcView);
199
200     if(!prcView)
201         return E_INVALIDARG;
202
203     if(This->hwnd) {
204         GetClientRect(This->hwnd, &rect);
205         if(memcmp(prcView, &rect, sizeof(RECT))) {
206             InvalidateRect(This->hwnd,NULL,TRUE);
207             SetWindowPos(This->hwnd, NULL, prcView->left, prcView->top, prcView->right,
208                     prcView->bottom, SWP_NOZORDER | SWP_NOACTIVATE);
209         }
210     }
211     
212     return S_OK;
213 }
214
215 static HRESULT WINAPI OleDocumentView_GetRect(IOleDocumentView *iface, LPRECT prcView)
216 {
217     HTMLDocument *This = DOCVIEW_THIS(iface);
218
219     TRACE("(%p)->(%p)\n", This, prcView);
220
221     if(!prcView)
222         return E_INVALIDARG;
223
224     GetClientRect(This->hwnd, prcView);
225     return S_OK;
226 }
227
228 static HRESULT WINAPI OleDocumentView_SetRectComplex(IOleDocumentView *iface, LPRECT prcView,
229                         LPRECT prcHScroll, LPRECT prcVScroll, LPRECT prcSizeBox)
230 {
231     HTMLDocument *This = DOCVIEW_THIS(iface);
232     FIXME("(%p)->(%p %p %p %p)\n", This, prcView, prcHScroll, prcVScroll, prcSizeBox);
233     return E_NOTIMPL;
234 }
235
236 static HRESULT WINAPI OleDocumentView_Show(IOleDocumentView *iface, BOOL fShow)
237 {
238     HTMLDocument *This = DOCVIEW_THIS(iface);
239     TRACE("(%p)->(%x)\n", This, fShow);
240
241     if(This->hwnd)
242         ShowWindow(This->hwnd, fShow);
243
244     return S_OK;
245 }
246
247 static HRESULT WINAPI OleDocumentView_UIActivate(IOleDocumentView *iface, BOOL fUIActivate)
248 {
249     HTMLDocument *This = DOCVIEW_THIS(iface);
250     HRESULT hres;
251     IOleInPlaceUIWindow *pIPWnd;
252     IOleInPlaceFrame *pIPFrame;
253     RECT posrect, cliprect;
254     OLEINPLACEFRAMEINFO frameinfo;
255     HWND parent_hwnd;
256
257     TRACE("(%p)->(%x)\n", This, fUIActivate);
258
259     if(!This->ipsite) {
260         FIXME("This->ipsite = NULL\n");
261         return E_FAIL;
262     }
263
264     if(fUIActivate) {
265         if(This->ui_active)
266             return S_OK;
267         if(!serverwnd_class)
268             register_serverwnd_class();
269
270         hres = IOleInPlaceSite_CanInPlaceActivate(This->ipsite);
271         if(hres != S_OK) {
272             WARN("CanInPlaceActivate returned: %08lx\n", hres);
273             return FAILED(hres) ? hres : E_FAIL;
274         }
275
276         hres = IOleInPlaceSite_GetWindowContext(This->ipsite, &pIPFrame, &pIPWnd, &posrect, &cliprect, &frameinfo);
277         if(FAILED(hres)) {
278             WARN("GetWindowContext failed: %08lx\n", hres);
279             return hres;
280         }
281         if(pIPWnd)
282             IOleInPlaceUIWindow_Release(pIPWnd);
283         TRACE("got window context: %p %p {%ld %ld %ld %ld} {%ld %ld %ld %ld} {%d %x %p %p %d}\n",
284                 pIPFrame, pIPWnd, posrect.left, posrect.top, posrect.right, posrect.bottom,
285                 cliprect.left, cliprect.top, cliprect.right, cliprect.bottom,
286                 frameinfo.cb, frameinfo.fMDIApp, frameinfo.hwndFrame, frameinfo.haccel, frameinfo.cAccelEntries);
287
288         hres = IOleInPlaceSite_GetWindow(This->ipsite, &parent_hwnd);
289         if(FAILED(hres)) {
290             WARN("GetWindow failed: %08lx\n", hres);
291             return hres;
292         }
293
294         TRACE("got parent window %p\n", parent_hwnd);
295
296         if(This->hwnd) {
297             if(GetParent(This->hwnd) != parent_hwnd)
298                 SetParent(This->hwnd, parent_hwnd);
299             SetWindowPos(This->hwnd, HWND_TOP,
300                     posrect.left, posrect.top, posrect.right-posrect.left, posrect.bottom-posrect.top,
301                     SWP_NOACTIVATE | SWP_SHOWWINDOW);
302         }else {
303             CreateWindowExW(0, wszInternetExplorer_Server, NULL,
304                     WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
305                     posrect.left, posrect.top, posrect.right-posrect.left, posrect.bottom-posrect.top,
306                     parent_hwnd, NULL, hInst, This);
307
308             TRACE("Created window %p\n", This->hwnd);
309
310             SetWindowPos(This->hwnd, NULL, 0, 0, 0, 0,
311                     SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_SHOWWINDOW);
312             RedrawWindow(This->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOERASE | RDW_ALLCHILDREN);
313             SetFocus(This->hwnd);
314         }
315
316         This->in_place_active = TRUE;
317         hres = IOleInPlaceSite_OnInPlaceActivate(This->ipsite);
318         if(FAILED(hres)) {
319             WARN("OnInPlaceActivate failed: %08lx\n", hres);
320             This->in_place_active = FALSE;
321             return hres;
322         }
323
324         /* NOTE:
325          * Windows implementation calls:
326          * RegisterWindowMessage("MSWHEEL_ROLLMSG");
327          * SetTimer(This->hwnd, TIMER_ID, 100, NULL);
328          */
329
330         This->ui_active = TRUE;
331         hres = IOleInPlaceSite_OnUIActivate(This->ipsite);
332         if(SUCCEEDED(hres)) {
333             IOleInPlaceFrame_SetActiveObject(pIPFrame, ACTOBJ(This), wszHTML_Document);
334         }else {
335             FIXME("OnUIActivate failed: %08lx\n", hres);
336             This->ui_active = FALSE;
337             return hres;
338         }
339         if(This->frame)
340             IOleInPlaceFrame_Release(This->frame);
341         This->frame = pIPFrame;
342
343         hres = IDocHostUIHandler_ShowUI(This->hostui, 0, ACTOBJ(This), CMDTARGET(This),
344                 pIPFrame, NULL);
345         if(FAILED(hres))
346             IDocHostUIHandler_HideUI(This->hostui);
347     }else {
348         This->ui_active = FALSE;
349         if(This->frame)
350             IOleInPlaceFrame_SetActiveObject(This->frame, NULL, NULL);
351         if(This->hostui)
352             IDocHostUIHandler_HideUI(This->hostui);
353         if(This->ipsite)
354             IOleInPlaceSite_OnUIDeactivate(This->ipsite, FALSE);
355     }
356     return S_OK;
357 }
358
359 static HRESULT WINAPI OleDocumentView_Open(IOleDocumentView *iface)
360 {
361     HTMLDocument *This = DOCVIEW_THIS(iface);
362     FIXME("(%p)\n", This);
363     return E_NOTIMPL;
364 }
365
366 static HRESULT WINAPI OleDocumentView_CloseView(IOleDocumentView *iface, DWORD dwReserved)
367 {
368     HTMLDocument *This = DOCVIEW_THIS(iface);
369     TRACE("(%p)->(%lx)\n", This, dwReserved);
370
371     if(dwReserved)
372         WARN("dwReserved = %ld\n", dwReserved);
373
374     /* NOTE:
375      * Windows implementation calls QueryInterface(IID_IOleCommandTarget),
376      * QueryInterface(IID_IOleControlSite) and KillTimer
377      */
378
379     IOleDocumentView_Show(iface, FALSE);
380
381     return S_OK;
382 }
383
384 static HRESULT WINAPI OleDocumentView_SaveViewState(IOleDocumentView *iface, LPSTREAM pstm)
385 {
386     HTMLDocument *This = DOCVIEW_THIS(iface);
387     FIXME("(%p)->(%p)\n", This, pstm);
388     return E_NOTIMPL;
389 }
390
391 static HRESULT WINAPI OleDocumentView_ApplyViewState(IOleDocumentView *iface, LPSTREAM pstm)
392 {
393     HTMLDocument *This = DOCVIEW_THIS(iface);
394     FIXME("(%p)->(%p)\n", This, pstm);
395     return E_NOTIMPL;
396 }
397
398 static HRESULT WINAPI OleDocumentView_Clone(IOleDocumentView *iface, IOleInPlaceSite *pIPSiteNew,
399                                         IOleDocumentView **ppViewNew)
400 {
401     HTMLDocument *This = DOCVIEW_THIS(iface);
402     FIXME("(%p)->(%p %p)\n", This, pIPSiteNew, ppViewNew);
403     return E_NOTIMPL;
404 }
405
406 #undef DOCVIEW_THIS
407
408 static const IOleDocumentViewVtbl OleDocumentViewVtbl = {
409     OleDocumentView_QueryInterface,
410     OleDocumentView_AddRef,
411     OleDocumentView_Release,
412     OleDocumentView_SetInPlaceSite,
413     OleDocumentView_GetInPlaceSite,
414     OleDocumentView_GetDocument,
415     OleDocumentView_SetRect,
416     OleDocumentView_GetRect,
417     OleDocumentView_SetRectComplex,
418     OleDocumentView_Show,
419     OleDocumentView_UIActivate,
420     OleDocumentView_Open,
421     OleDocumentView_CloseView,
422     OleDocumentView_SaveViewState,
423     OleDocumentView_ApplyViewState,
424     OleDocumentView_Clone
425 };
426
427 /**********************************************************
428  * IViewObject implementation
429  */
430
431 #define VIEWOBJ_THIS(iface) DEFINE_THIS(HTMLDocument, ViewObject2, iface)
432
433 static HRESULT WINAPI ViewObject_QueryInterface(IViewObject2 *iface, REFIID riid, void **ppvObject)
434 {
435     HTMLDocument *This = VIEWOBJ_THIS(iface);
436     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
437 }
438
439 static ULONG WINAPI ViewObject_AddRef(IViewObject2 *iface)
440 {
441     HTMLDocument *This = VIEWOBJ_THIS(iface);
442     return IHTMLDocument2_AddRef(HTMLDOC(This));
443 }
444
445 static ULONG WINAPI ViewObject_Release(IViewObject2 *iface)
446 {
447     HTMLDocument *This = VIEWOBJ_THIS(iface);
448     return IHTMLDocument2_Release(HTMLDOC(This));
449 }
450
451 static HRESULT WINAPI ViewObject_Draw(IViewObject2 *iface, DWORD dwDrawAspect, LONG lindex, void *pvAspect,
452         DVTARGETDEVICE *ptd, HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds,
453         LPCRECTL lprcWBounds, BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue), ULONG_PTR dwContinue)
454 {
455     HTMLDocument *This = VIEWOBJ_THIS(iface);
456     FIXME("(%p)->(%ld %ld %p %p %p %p %p %p %p %ld)\n", This, dwDrawAspect, lindex, pvAspect,
457             ptd, hdcTargetDev, hdcDraw, lprcBounds, lprcWBounds, pfnContinue, dwContinue);
458     return E_NOTIMPL;
459 }
460
461 static HRESULT WINAPI ViewObject_GetColorSet(IViewObject2 *iface, DWORD dwDrawAspect, LONG lindex, void *pvAspect,
462         DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **ppColorSet)
463 {
464     HTMLDocument *This = VIEWOBJ_THIS(iface);
465     FIXME("(%p)->(%ld %ld %p %p %p %p)\n", This, dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev, ppColorSet);
466     return E_NOTIMPL;
467 }
468
469 static HRESULT WINAPI ViewObject_Freeze(IViewObject2 *iface, DWORD dwDrawAspect, LONG lindex,
470         void *pvAspect, DWORD *pdwFreeze)
471 {
472     HTMLDocument *This = VIEWOBJ_THIS(iface);
473     FIXME("(%p)->(%ld %ld %p %p)\n", This, dwDrawAspect, lindex, pvAspect, pdwFreeze);
474     return E_NOTIMPL;
475 }
476
477 static HRESULT WINAPI ViewObject_Unfreeze(IViewObject2 *iface, DWORD dwFreeze)
478 {
479     HTMLDocument *This = VIEWOBJ_THIS(iface);
480     FIXME("(%p)->(%ld)\n", This, dwFreeze);
481     return E_NOTIMPL;
482 }
483
484 static HRESULT WINAPI ViewObject_SetAdvise(IViewObject2 *iface, DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
485 {
486     HTMLDocument *This = VIEWOBJ_THIS(iface);
487     FIXME("(%p)->(%ld %ld %p)\n", This, aspects, advf, pAdvSink);
488     return E_NOTIMPL;
489 }
490
491 static HRESULT WINAPI ViewObject_GetAdvise(IViewObject2 *iface, DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
492 {
493     HTMLDocument *This = VIEWOBJ_THIS(iface);
494     FIXME("(%p)->(%p %p %p)\n", This, pAspects, pAdvf, ppAdvSink);
495     return E_NOTIMPL;
496 }
497
498 static HRESULT WINAPI ViewObject_GetExtent(IViewObject2 *iface, DWORD dwDrawAspect, LONG lindex,
499                                 DVTARGETDEVICE* ptd, LPSIZEL lpsizel)
500 {
501     HTMLDocument *This = VIEWOBJ_THIS(iface);
502     FIXME("(%p)->(%ld %ld %p %p)\n", This, dwDrawAspect, lindex, ptd, lpsizel);
503     return E_NOTIMPL;
504 }
505
506 #undef VIEWOBJ_THIS
507
508 static const IViewObject2Vtbl ViewObjectVtbl = {
509     ViewObject_QueryInterface,
510     ViewObject_AddRef,
511     ViewObject_Release,
512     ViewObject_Draw,
513     ViewObject_GetColorSet,
514     ViewObject_Freeze,
515     ViewObject_Unfreeze,
516     ViewObject_SetAdvise,
517     ViewObject_GetAdvise,
518     ViewObject_GetExtent
519 };
520
521 void HTMLDocument_View_Init(HTMLDocument *This)
522 {
523     This->lpOleDocumentViewVtbl = &OleDocumentViewVtbl;
524     This->lpViewObject2Vtbl = &ViewObjectVtbl;
525
526     This->ipsite = NULL;
527     This->frame = NULL;
528     This->hwnd = NULL;
529
530     This->in_place_active = FALSE;
531     This->ui_active = FALSE;
532 }