1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * Copyright 2004, 2005 Martin Fuchs
3*c2c66affSColin Finck  *
4*c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5*c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6*c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7*c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8*c2c66affSColin Finck  *
9*c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10*c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12*c2c66affSColin Finck  * Lesser General Public License for more details.
13*c2c66affSColin Finck  *
14*c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15*c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16*c2c66affSColin Finck  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17*c2c66affSColin Finck  */
18*c2c66affSColin Finck 
19*c2c66affSColin Finck 
20*c2c66affSColin Finck  //
21*c2c66affSColin Finck  // Explorer clone
22*c2c66affSColin Finck  //
23*c2c66affSColin Finck  // webchild.cpp
24*c2c66affSColin Finck  //
25*c2c66affSColin Finck  // Martin Fuchs, 08.02.2004
26*c2c66affSColin Finck  //
27*c2c66affSColin Finck 
28*c2c66affSColin Finck #include <precomp.h>
29*c2c66affSColin Finck 
30*c2c66affSColin Finck #include "webchild.h"
31*c2c66affSColin Finck 
32*c2c66affSColin Finck #include <comutil.h>
33*c2c66affSColin Finck 
Variant(const VARIANT & var)34*c2c66affSColin Finck Variant::Variant(const VARIANT& var)
35*c2c66affSColin Finck {
36*c2c66affSColin Finck 	VariantInit(this);
37*c2c66affSColin Finck 	CheckError(VariantCopy(this, const_cast<VARIANT*>(&var)));
38*c2c66affSColin Finck }
39*c2c66affSColin Finck 
Variant(const VARIANT * var)40*c2c66affSColin Finck Variant::Variant(const VARIANT* var)
41*c2c66affSColin Finck {
42*c2c66affSColin Finck 	VariantInit(this);
43*c2c66affSColin Finck 	CheckError(VariantCopy(this, const_cast<VARIANT*>(var)));
44*c2c66affSColin Finck }
45*c2c66affSColin Finck 
~Variant()46*c2c66affSColin Finck Variant::~Variant()
47*c2c66affSColin Finck {
48*c2c66affSColin Finck 	VariantClear(this);
49*c2c66affSColin Finck }
50*c2c66affSColin Finck 
51*c2c66affSColin Finck 
operator long() const52*c2c66affSColin Finck Variant::operator long() const
53*c2c66affSColin Finck {
54*c2c66affSColin Finck 	Variant v;
55*c2c66affSColin Finck 	CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_I4));
56*c2c66affSColin Finck 	return V_I4(&v);
57*c2c66affSColin Finck }
58*c2c66affSColin Finck 
operator bool() const59*c2c66affSColin Finck Variant::operator bool() const
60*c2c66affSColin Finck {
61*c2c66affSColin Finck 	Variant v;
62*c2c66affSColin Finck 	CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_BOOL));
63*c2c66affSColin Finck 	return V_BOOL(&v)? true: false;
64*c2c66affSColin Finck }
65*c2c66affSColin Finck 
operator IDispatch*() const66*c2c66affSColin Finck Variant::operator IDispatch*() const
67*c2c66affSColin Finck {
68*c2c66affSColin Finck 	Variant v;
69*c2c66affSColin Finck 	CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_DISPATCH));
70*c2c66affSColin Finck 	return V_DISPATCH(&v);
71*c2c66affSColin Finck }
72*c2c66affSColin Finck 
operator VARIANT_BOOL() const73*c2c66affSColin Finck Variant::operator VARIANT_BOOL() const
74*c2c66affSColin Finck {
75*c2c66affSColin Finck 	Variant v;
76*c2c66affSColin Finck 	CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_BOOL));
77*c2c66affSColin Finck 	return V_BOOL(&v);
78*c2c66affSColin Finck }
79*c2c66affSColin Finck 
80*c2c66affSColin Finck 
assign(BSTR s)81*c2c66affSColin Finck void BStr::assign(BSTR s)
82*c2c66affSColin Finck {
83*c2c66affSColin Finck 	if (!SysReAllocString(&_p, s))
84*c2c66affSColin Finck 		THROW_EXCEPTION(E_OUTOFMEMORY);
85*c2c66affSColin Finck }
86*c2c66affSColin Finck 
assign(const VARIANT & var)87*c2c66affSColin Finck void BStr::assign(const VARIANT& var)
88*c2c66affSColin Finck {
89*c2c66affSColin Finck 	if (V_VT(&var) == VT_BSTR)
90*c2c66affSColin Finck 		assign(V_BSTR(&var));
91*c2c66affSColin Finck 	else {
92*c2c66affSColin Finck 		Variant v;
93*c2c66affSColin Finck 		CheckError(VariantChangeType(&v, const_cast<VARIANT*>(&var), 0, VT_BSTR));
94*c2c66affSColin Finck 		assign(V_BSTR(&v));
95*c2c66affSColin Finck 	}
96*c2c66affSColin Finck }
97*c2c66affSColin Finck 
98*c2c66affSColin Finck 
BrowserNavigator()99*c2c66affSColin Finck BrowserNavigator::BrowserNavigator()
100*c2c66affSColin Finck  :	_browser_initialized(false)
101*c2c66affSColin Finck {
102*c2c66affSColin Finck }
103*c2c66affSColin Finck 
attach(IWebBrowser * browser)104*c2c66affSColin Finck void BrowserNavigator::attach(IWebBrowser* browser)
105*c2c66affSColin Finck {
106*c2c66affSColin Finck 	_browser = browser;
107*c2c66affSColin Finck }
108*c2c66affSColin Finck 
goto_url(LPCTSTR url)109*c2c66affSColin Finck void BrowserNavigator::goto_url(LPCTSTR url)
110*c2c66affSColin Finck {
111*c2c66affSColin Finck 	if (_browser_initialized)
112*c2c66affSColin Finck 		_browser->Navigate(BStr(url), NULL, NULL, NULL, NULL);
113*c2c66affSColin Finck 	else {
114*c2c66affSColin Finck 		_new_url = url;
115*c2c66affSColin Finck 
116*c2c66affSColin Finck 		_browser->Navigate(BStr(L"about:blank"), NULL, NULL, NULL, NULL);
117*c2c66affSColin Finck 	}
118*c2c66affSColin Finck }
119*c2c66affSColin Finck 
set_html_page(const String & html_txt)120*c2c66affSColin Finck void BrowserNavigator::set_html_page(const String& html_txt)
121*c2c66affSColin Finck {
122*c2c66affSColin Finck 	_new_html_txt = html_txt;
123*c2c66affSColin Finck 
124*c2c66affSColin Finck 	goto_url(TEXT("about:blank"));
125*c2c66affSColin Finck }
126*c2c66affSColin Finck 
T2nA_binary(LPCTSTR s,LPSTR d,int len)127*c2c66affSColin Finck void T2nA_binary(LPCTSTR s, LPSTR d, int len)
128*c2c66affSColin Finck {
129*c2c66affSColin Finck 	while(len-- > 0)
130*c2c66affSColin Finck 		*d++ = (unsigned char)*s++;
131*c2c66affSColin Finck }
132*c2c66affSColin Finck 
navigated(LPCTSTR url)133*c2c66affSColin Finck void BrowserNavigator::navigated(LPCTSTR url)
134*c2c66affSColin Finck {
135*c2c66affSColin Finck 	_browser_initialized = true;
136*c2c66affSColin Finck 
137*c2c66affSColin Finck 	bool nav = false;
138*c2c66affSColin Finck 
139*c2c66affSColin Finck 	if (!_new_url.empty()) {
140*c2c66affSColin Finck 		if (!_tcscmp(url,TEXT("about:blank")) && _new_url!=TEXT("about:blank")) {
141*c2c66affSColin Finck 			_browser->Navigate(BStr(_new_url), NULL, NULL, NULL, NULL);
142*c2c66affSColin Finck 			++nav;
143*c2c66affSColin Finck 		}
144*c2c66affSColin Finck 
145*c2c66affSColin Finck 		_new_url.erase();
146*c2c66affSColin Finck 	}
147*c2c66affSColin Finck 
148*c2c66affSColin Finck 	if (!nav && !_new_html_txt.empty()) {	///@todo move this into DocumentComplete() ?
149*c2c66affSColin Finck 		int len = _new_html_txt.length();
150*c2c66affSColin Finck 		HGLOBAL hHtmlText = GlobalAlloc(GPTR, len);
151*c2c66affSColin Finck 
152*c2c66affSColin Finck 		if (!hHtmlText) {
153*c2c66affSColin Finck 			T2nA_binary(_new_html_txt, (char*)hHtmlText, len);
154*c2c66affSColin Finck 			_new_html_txt.erase();
155*c2c66affSColin Finck 
156*c2c66affSColin Finck 			SIfacePtr<IStream> pStream;
157*c2c66affSColin Finck 			HRESULT hr = CreateStreamOnHGlobal(hHtmlText, TRUE, &pStream);
158*c2c66affSColin Finck 
159*c2c66affSColin Finck 			if (SUCCEEDED(hr)) {
160*c2c66affSColin Finck 				SIfacePtr<IDispatch> pHtmlDoc;
161*c2c66affSColin Finck 				CheckError(_browser->get_Document(&pHtmlDoc));
162*c2c66affSColin Finck 
163*c2c66affSColin Finck 				SIfacePtr<IPersistStreamInit> pPersistStreamInit;
164*c2c66affSColin Finck 				pHtmlDoc.QueryInterface(IID_IPersistStreamInit, &pPersistStreamInit);
165*c2c66affSColin Finck 
166*c2c66affSColin Finck 				CheckError(pPersistStreamInit->InitNew());
167*c2c66affSColin Finck 				CheckError(pPersistStreamInit->Load(pStream));
168*c2c66affSColin Finck 			} else
169*c2c66affSColin Finck 				GlobalFree(hHtmlText);
170*c2c66affSColin Finck 		}
171*c2c66affSColin Finck 	}
172*c2c66affSColin Finck }
173*c2c66affSColin Finck 
174*c2c66affSColin Finck 
create_webchildwindow(const WebChildWndInfo & info)175*c2c66affSColin Finck HWND create_webchildwindow(const WebChildWndInfo& info)
176*c2c66affSColin Finck {
177*c2c66affSColin Finck 	WebChildWindow* pWnd = WebChildWindow::create(info);
178*c2c66affSColin Finck 
179*c2c66affSColin Finck 	if (!pWnd)
180*c2c66affSColin Finck 		return 0;
181*c2c66affSColin Finck 
182*c2c66affSColin Finck 	return *pWnd;
183*c2c66affSColin Finck }
184*c2c66affSColin Finck 
185*c2c66affSColin Finck static const CLSID CLSID_MozillaBrowser =
186*c2c66affSColin Finck 	{0x1339B54C, 0x3453, 0x11D2, {0x93, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
187*c2c66affSColin Finck 
188*c2c66affSColin Finck 
WebChildWindow(HWND hwnd,const WebChildWndInfo & info)189*c2c66affSColin Finck WebChildWindow::WebChildWindow(HWND hwnd, const WebChildWndInfo& info)
190*c2c66affSColin Finck  :	super(hwnd, info),
191*c2c66affSColin Finck 	web_super(_navigator)
192*c2c66affSColin Finck {
193*c2c66affSColin Finck 	 // first try to create a web control with MS IE's CLASSID
194*c2c66affSColin Finck 	HRESULT hr = create_control(hwnd, CLSID_WebBrowser, IID_IWebBrowser2);
195*c2c66affSColin Finck 
196*c2c66affSColin Finck 	 // If this failed, try to use Mozilla's web control
197*c2c66affSColin Finck 	if (FAILED(hr))
198*c2c66affSColin Finck 		hr = create_control(hwnd, CLSID_MozillaBrowser, IID_IWebBrowser2);
199*c2c66affSColin Finck 
200*c2c66affSColin Finck 	if (SUCCEEDED(hr)) {
201*c2c66affSColin Finck 		_navigator.attach(_control);
202*c2c66affSColin Finck 
203*c2c66affSColin Finck 		_connector = auto_ptr<EventConnector>(new EventConnector(_control, DIID_DWebBrowserEvents2, this));
204*c2c66affSColin Finck 
205*c2c66affSColin Finck 		_control->Navigate(BStr(info._path), &vtMissing, &vtMissing, &vtMissing, &vtMissing);
206*c2c66affSColin Finck 		//browser->Navigate2(&Variant(info._path), &vtMissing, &vtMissing, &vtMissing, &vtMissing);
207*c2c66affSColin Finck 	}
208*c2c66affSColin Finck }
209*c2c66affSColin Finck 
WndProc(UINT nmsg,WPARAM wparam,LPARAM lparam)210*c2c66affSColin Finck LRESULT WebChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
211*c2c66affSColin Finck {
212*c2c66affSColin Finck 	try {
213*c2c66affSColin Finck 		switch(nmsg) {
214*c2c66affSColin Finck 		  case WM_ERASEBKGND:
215*c2c66affSColin Finck 			if (!_control) {
216*c2c66affSColin Finck 				HDC hdc = (HDC)wparam;
217*c2c66affSColin Finck 				ClientRect rect(_hwnd);
218*c2c66affSColin Finck 
219*c2c66affSColin Finck 				HBRUSH hbrush = CreateSolidBrush(RGB(200,200,235));
220*c2c66affSColin Finck 				BkMode mode(hdc, TRANSPARENT);
221*c2c66affSColin Finck 				TextColor color(hdc, RGB(200,40,40));
222*c2c66affSColin Finck 				FillRect(hdc, &rect, hbrush);
223*c2c66affSColin Finck 				DrawText(hdc, TEXT("Sorry - no web browser control could be loaded."), -1, &rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
224*c2c66affSColin Finck 				DeleteObject(hbrush);
225*c2c66affSColin Finck 			}
226*c2c66affSColin Finck 
227*c2c66affSColin Finck 			return TRUE;
228*c2c66affSColin Finck 
229*c2c66affSColin Finck  		  case PM_DISPATCH_COMMAND: {
230*c2c66affSColin Finck 			if (!_control)
231*c2c66affSColin Finck 				return FALSE;
232*c2c66affSColin Finck 
233*c2c66affSColin Finck 			HRESULT hr = E_FAIL;
234*c2c66affSColin Finck 
235*c2c66affSColin Finck 			switch(LOWORD(wparam)) {
236*c2c66affSColin Finck 			  case ID_GO_BACK:
237*c2c66affSColin Finck 				hr = _control->GoBack();
238*c2c66affSColin Finck 				break;
239*c2c66affSColin Finck 
240*c2c66affSColin Finck 			  case ID_GO_FORWARD:
241*c2c66affSColin Finck 				hr = _control->GoForward();
242*c2c66affSColin Finck 				break;
243*c2c66affSColin Finck 
244*c2c66affSColin Finck 			  case ID_GO_UP:
245*c2c66affSColin Finck 				///@todo
246*c2c66affSColin Finck 				break;
247*c2c66affSColin Finck 
248*c2c66affSColin Finck 			  case ID_GO_HOME:
249*c2c66affSColin Finck 				hr = _control->GoHome();
250*c2c66affSColin Finck 				break;
251*c2c66affSColin Finck 
252*c2c66affSColin Finck 			  case ID_GO_SEARCH:
253*c2c66affSColin Finck 				hr = _control->GoSearch();
254*c2c66affSColin Finck 				break;
255*c2c66affSColin Finck 
256*c2c66affSColin Finck 			  case ID_REFRESH:
257*c2c66affSColin Finck 				hr = _control->Refresh();
258*c2c66affSColin Finck 				break;
259*c2c66affSColin Finck 
260*c2c66affSColin Finck 			  case ID_STOP:
261*c2c66affSColin Finck 				hr = _control->Stop();
262*c2c66affSColin Finck 				break;
263*c2c66affSColin Finck 
264*c2c66affSColin Finck 			  default:
265*c2c66affSColin Finck 				return super::WndProc(nmsg, wparam, lparam);
266*c2c66affSColin Finck 			}
267*c2c66affSColin Finck 
268*c2c66affSColin Finck 			if (FAILED(hr) && hr!=E_FAIL)
269*c2c66affSColin Finck 				THROW_EXCEPTION(hr);
270*c2c66affSColin Finck 
271*c2c66affSColin Finck 			return TRUE;}
272*c2c66affSColin Finck 
273*c2c66affSColin Finck 		  default:
274*c2c66affSColin Finck 			return super::WndProc(nmsg, wparam, lparam);
275*c2c66affSColin Finck 		}
276*c2c66affSColin Finck 	} catch(COMException& e) {
277*c2c66affSColin Finck 		HandleException(e, _hwnd);
278*c2c66affSColin Finck 	}
279*c2c66affSColin Finck 
280*c2c66affSColin Finck 	return 0;
281*c2c66affSColin Finck }
282*c2c66affSColin Finck 
283*c2c66affSColin Finck 
jump_to_int(LPCTSTR url)284*c2c66affSColin Finck String WebChildWindow::jump_to_int(LPCTSTR url)
285*c2c66affSColin Finck {
286*c2c66affSColin Finck 	_navigator.goto_url(url);
287*c2c66affSColin Finck 
288*c2c66affSColin Finck 	return url;
289*c2c66affSColin Finck }
290