1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include "helpinterceptor.hxx"
32 #include "helpdispatch.hxx"
33 #include "newhelp.hxx"
34 #include <sfx2/sfxuno.hxx>
35 #include <tools/urlobj.hxx>
36 #include <tools/debug.hxx>
37 #include <com/sun/star/beans/PropertyValue.hpp>
38 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
39 #include <cppuhelper/interfacecontainer.h>
40 #include <vcl/window.hxx>
41 #include <limits.h>
42 
43 using namespace ::com::sun::star::beans;
44 using namespace ::com::sun::star::frame;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::util;
47 using namespace ::com::sun::star::lang;
48 
49 extern void AppendConfigToken_Impl( String& rURL, sal_Bool bQuestionMark ); // sfxhelp.cxx
50 
51 // class HelpInterceptor_Impl --------------------------------------------
52 
53 HelpInterceptor_Impl::HelpInterceptor_Impl() :
54 
55 	m_pHistory	( NULL ),
56 	m_nCurPos	( 0 )
57 
58 {
59 }
60 
61 // -----------------------------------------------------------------------
62 
63 HelpInterceptor_Impl::~HelpInterceptor_Impl()
64 {
65 	for ( sal_uInt16 i = 0; m_pHistory && i < m_pHistory->Count(); ++i )
66 		delete m_pHistory->GetObject(i);
67 	delete m_pHistory;
68 }
69 
70 // -----------------------------------------------------------------------
71 
72 void HelpInterceptor_Impl::addURL( const String& rURL )
73 {
74   if ( !m_pHistory )
75 		m_pHistory = new HelpHistoryList_Impl;
76 	sal_uIntPtr nCount = m_pHistory->Count();
77 	if ( nCount && m_nCurPos < ( nCount - 1 ) )
78 	{
79 		for ( sal_uIntPtr i = nCount - 1; i > m_nCurPos; i-- )
80 			delete m_pHistory->Remove(i);
81 	}
82     Reference<XFrame> xFrame(m_xIntercepted, UNO_QUERY);
83     Reference<XController> xController;
84     if(xFrame.is())
85         xController = xFrame->getController();
86     Any aViewData;
87     if(xController.is() && m_pHistory->Count())
88 	{
89 		m_pHistory->GetObject(m_nCurPos)->aViewData = xController->getViewData();
90 	}
91 
92 	m_aCurrentURL = rURL;
93 	Any aEmptyViewData;
94     m_pHistory->Insert( new HelpHistoryEntry_Impl( rURL, aEmptyViewData ), LIST_APPEND );
95 	m_nCurPos = m_pHistory->Count() - 1;
96 // TODO ?
97 	if ( m_xListener.is() )
98 	{
99 		::com::sun::star::frame::FeatureStateEvent aEvent;
100 		URL aURL;
101 	    aURL.Complete = rURL;
102 		aEvent.FeatureURL = aURL;
103         aEvent.Source = (::com::sun::star::frame::XDispatch*)this;
104 		m_xListener->statusChanged( aEvent );
105 	}
106 
107 	m_pWindow->UpdateToolbox();
108 }
109 
110 // -----------------------------------------------------------------------
111 
112 void HelpInterceptor_Impl::setInterception( Reference< XFrame > xFrame )
113 {
114 	m_xIntercepted = Reference< XDispatchProviderInterception>( xFrame, UNO_QUERY );
115 
116 	if ( m_xIntercepted.is() )
117 		m_xIntercepted->registerDispatchProviderInterceptor( (XDispatchProviderInterceptor*)this );
118 }
119 
120 // -----------------------------------------------------------------------
121 
122 void HelpInterceptor_Impl::SetStartURL( const String& rURL )
123 {
124 	DBG_ASSERT( !m_pHistory, "invalid history" );
125 	if ( !m_pHistory )
126 	{
127 		m_pHistory = new HelpHistoryList_Impl;
128         Any aEmptyViewData;
129         m_pHistory->Insert( new HelpHistoryEntry_Impl( rURL, aEmptyViewData ), ((sal_uIntPtr)0x0) );
130 		m_nCurPos = m_pHistory->Count() - 1;
131 
132 		m_pWindow->UpdateToolbox();
133 	}
134 	m_aCurrentURL = rURL;
135 }
136 
137 sal_Bool HelpInterceptor_Impl::HasHistoryPred() const
138 {
139 	return m_pHistory && ( m_nCurPos > 0 );
140 }
141 
142 sal_Bool HelpInterceptor_Impl::HasHistorySucc() const
143 {
144 	return m_pHistory && ( m_nCurPos < ( m_pHistory->Count() - 1 ) );
145 }
146 
147 
148 // -----------------------------------------------------------------------
149 // XDispatchProvider
150 
151 Reference< XDispatch > SAL_CALL HelpInterceptor_Impl::queryDispatch(
152 
153 	const URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags )
154 
155 	throw( RuntimeException )
156 
157 {
158 	Reference< XDispatch > xResult;
159 	if ( m_xSlaveDispatcher.is() )
160 		xResult = m_xSlaveDispatcher->queryDispatch( aURL, aTargetFrameName, nSearchFlags );
161 
162 	// INetURLObject aObj( aURL.Complete );
163 	// sal_Bool bHelpURL = ( aObj.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP );
164     sal_Bool bHelpURL = aURL.Complete.toAsciiLowerCase().match(rtl::OUString::createFromAscii("vnd.sun.star.help"),0);
165 
166 	if ( bHelpURL )
167 	{
168 		DBG_ASSERT( xResult.is(), "invalid dispatch" );
169 	    HelpDispatch_Impl* pHelpDispatch = new HelpDispatch_Impl( *this, xResult );
170     	xResult = Reference< XDispatch >( static_cast< ::cppu::OWeakObject* >(pHelpDispatch), UNO_QUERY );
171 	}
172 
173 	return xResult;
174 }
175 
176 // -----------------------------------------------------------------------
177 
178 Sequence < Reference < XDispatch > > SAL_CALL HelpInterceptor_Impl::queryDispatches(
179 
180 	const Sequence< DispatchDescriptor >& aDescripts )
181 
182 	throw( RuntimeException )
183 
184 {
185 	Sequence< Reference< XDispatch > > aReturn( aDescripts.getLength() );
186 	Reference< XDispatch >* pReturn = aReturn.getArray();
187 	const DispatchDescriptor* pDescripts = aDescripts.getConstArray();
188 	for ( sal_Int16 i = 0; i < aDescripts.getLength(); ++i, ++pReturn, ++pDescripts )
189 	{
190 		*pReturn = queryDispatch( pDescripts->FeatureURL, pDescripts->FrameName, pDescripts->SearchFlags );
191 	}
192 	return aReturn;
193 }
194 
195 // -----------------------------------------------------------------------
196 // XDispatchProviderInterceptor
197 
198 Reference< XDispatchProvider > SAL_CALL HelpInterceptor_Impl::getSlaveDispatchProvider()
199 
200 	throw( RuntimeException )
201 
202 {
203 	return m_xSlaveDispatcher;
204 }
205 
206 // -----------------------------------------------------------------------
207 
208 void SAL_CALL HelpInterceptor_Impl::setSlaveDispatchProvider( const Reference< XDispatchProvider >& xNewSlave )
209 
210 	throw( RuntimeException )
211 
212 {
213 	m_xSlaveDispatcher = xNewSlave;
214 }
215 
216 // -----------------------------------------------------------------------
217 
218 Reference< XDispatchProvider > SAL_CALL HelpInterceptor_Impl::getMasterDispatchProvider()
219 
220 	throw( RuntimeException )
221 
222 {
223 	return m_xMasterDispatcher;
224 }
225 
226 // -----------------------------------------------------------------------
227 
228 void SAL_CALL HelpInterceptor_Impl::setMasterDispatchProvider( const Reference< XDispatchProvider >& xNewMaster )
229 
230 	throw( RuntimeException )
231 
232 {
233 	m_xMasterDispatcher = xNewMaster;
234 }
235 
236 // -----------------------------------------------------------------------
237 // XInterceptorInfo
238 
239 Sequence< ::rtl::OUString > SAL_CALL HelpInterceptor_Impl::getInterceptedURLs()
240 
241 	throw( RuntimeException )
242 
243 {
244 	Sequence< ::rtl::OUString > aURLList( 1 );
245 	aURLList[0] = DEFINE_CONST_UNICODE("vnd.sun.star.help://*");
246 	return aURLList;;
247 }
248 
249 // -----------------------------------------------------------------------
250 // XDispatch
251 
252 void SAL_CALL HelpInterceptor_Impl::dispatch(
253 	const URL& aURL, const Sequence< ::com::sun::star::beans::PropertyValue >& ) throw( RuntimeException )
254 {
255 	sal_Bool bBack = ( String( DEFINE_CONST_UNICODE(".uno:Backward") ) == String( aURL.Complete ) );
256 	if ( bBack || String( DEFINE_CONST_UNICODE(".uno:Forward") ) == String( aURL.Complete ) )
257 	{
258 		if ( m_pHistory )
259 		{
260 			if(m_pHistory->Count() > m_nCurPos)
261 			{
262 				Reference<XFrame> xFrame(m_xIntercepted, UNO_QUERY);
263                 Reference<XController> xController;
264                 if(xFrame.is())
265                     xController = xFrame->getController();
266 				if(xController.is())
267 				{
268 					m_pHistory->GetObject(m_nCurPos)->aViewData = xController->getViewData();
269 				}
270 			}
271 
272 			sal_uIntPtr nPos = ( bBack && m_nCurPos > 0 ) ? --m_nCurPos
273 													: ( !bBack && m_nCurPos < m_pHistory->Count() - 1 )
274 													? ++m_nCurPos
275 													: ULONG_MAX;
276 
277 			if ( nPos < ULONG_MAX )
278 			{
279 				HelpHistoryEntry_Impl* pEntry = m_pHistory->GetObject( nPos );
280 				if ( pEntry )
281                     m_pWindow->loadHelpContent(pEntry->aURL, sal_False); // false => dont add item to history again!
282 			}
283 
284 			m_pWindow->UpdateToolbox();
285 		}
286 	}
287 }
288 
289 // -----------------------------------------------------------------------
290 
291 void SAL_CALL HelpInterceptor_Impl::addStatusListener(
292 	const Reference< XStatusListener >& xControl, const URL& ) throw( RuntimeException )
293 {
294 	DBG_ASSERT( !m_xListener.is(), "listener already exists" );
295 	m_xListener = xControl;
296 }
297 
298 // -----------------------------------------------------------------------
299 
300 void SAL_CALL HelpInterceptor_Impl::removeStatusListener(
301 	const Reference< XStatusListener >&, const URL&) throw( RuntimeException )
302 {
303 	m_xListener = 0;
304 }
305 
306 // HelpListener_Impl -----------------------------------------------------
307 
308 HelpListener_Impl::HelpListener_Impl( HelpInterceptor_Impl* pInter )
309 {
310 	pInterceptor = pInter;
311     pInterceptor->addStatusListener( this, ::com::sun::star::util::URL() );
312 }
313 
314 // -----------------------------------------------------------------------
315 
316 void SAL_CALL HelpListener_Impl::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event )
317 
318 	throw( ::com::sun::star::uno::RuntimeException )
319 
320 {
321 	INetURLObject aObj( Event.FeatureURL.Complete );
322 	aFactory = aObj.GetHost();
323 	aChangeLink.Call( this );
324 }
325 
326 // -----------------------------------------------------------------------
327 
328 void SAL_CALL HelpListener_Impl::disposing( const ::com::sun::star::lang::EventObject& )
329 
330 	throw( ::com::sun::star::uno::RuntimeException )
331 
332 {
333     pInterceptor->removeStatusListener( this, ::com::sun::star::util::URL() );
334     pInterceptor = NULL;
335 }
336 /*-- 05.09.2002 12:17:59---------------------------------------------------
337 
338   -----------------------------------------------------------------------*/
339 HelpStatusListener_Impl::HelpStatusListener_Impl(
340         Reference < XDispatch > aDispatch, URL& rURL)
341 {
342     aDispatch->addStatusListener(this, rURL);
343 }
344 /*-- 05.09.2002 12:17:59---------------------------------------------------
345 
346   -----------------------------------------------------------------------*/
347 HelpStatusListener_Impl::~HelpStatusListener_Impl()
348 {
349     if(xDispatch.is())
350         xDispatch->removeStatusListener(this, com::sun::star::util::URL());
351 }
352 /*-- 05.09.2002 12:17:59---------------------------------------------------
353 
354   -----------------------------------------------------------------------*/
355 void HelpStatusListener_Impl::statusChanged(
356     const FeatureStateEvent& rEvent ) throw( RuntimeException )
357 {
358     aStateEvent = rEvent;
359 }
360 /*-- 05.09.2002 12:18:00---------------------------------------------------
361 
362   -----------------------------------------------------------------------*/
363 void HelpStatusListener_Impl::disposing( const EventObject& ) throw( RuntimeException )
364 {
365     xDispatch->removeStatusListener(this, com::sun::star::util::URL());
366     xDispatch = 0;
367 }
368