Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "sfx2/sfxhelp.hxx"
21 :
22 : #include <set>
23 : #include <algorithm>
24 : #include <com/sun/star/uno/Reference.h>
25 : #include <com/sun/star/frame/XFrame.hpp>
26 : #include <com/sun/star/frame/XComponentLoader.hpp>
27 : #include <com/sun/star/lang/XComponent.hpp>
28 : #include <comphelper/processfactory.hxx>
29 : #include <com/sun/star/awt/XWindow.hpp>
30 : #include <com/sun/star/awt/XTopWindow.hpp>
31 : #include <com/sun/star/awt/PosSize.hpp>
32 : #include <com/sun/star/frame/XDesktop.hpp>
33 : #include <com/sun/star/util/URLTransformer.hpp>
34 : #include <com/sun/star/util/XURLTransformer.hpp>
35 : #include <com/sun/star/frame/XDispatch.hpp>
36 : #include <com/sun/star/frame/XDispatchProvider.hpp>
37 : #include <com/sun/star/beans/XPropertySet.hpp>
38 : #include <com/sun/star/frame/FrameSearchFlag.hpp>
39 : #include <toolkit/helper/vclunohelper.hxx>
40 : #include <com/sun/star/frame/ModuleManager.hpp>
41 : #include <com/sun/star/system/SystemShellExecute.hpp>
42 : #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
43 : #include <unotools/configmgr.hxx>
44 : #include <unotools/configitem.hxx>
45 : #include <svtools/helpopt.hxx>
46 : #include <unotools/moduleoptions.hxx>
47 : #include <tools/urlobj.hxx>
48 : #include <ucbhelper/content.hxx>
49 : #include <unotools/pathoptions.hxx>
50 : #include <rtl/ustring.hxx>
51 : #include <osl/process.h>
52 : #include <osl/file.hxx>
53 : #include <unotools/bootstrap.hxx>
54 : #include <rtl/uri.hxx>
55 : #include <vcl/msgbox.hxx>
56 : #include <svtools/ehdl.hxx>
57 : #include <svtools/sfxecode.hxx>
58 :
59 : #include "newhelp.hxx"
60 : #include <sfx2/objsh.hxx>
61 : #include <sfx2/docfac.hxx>
62 : #include "sfx2/sfxresid.hxx"
63 : #include "helper.hxx"
64 : #include "app.hrc"
65 : #include <sfx2/sfxuno.hxx>
66 : #include <vcl/svapp.hxx>
67 : #include <sfx2/frame.hxx>
68 : #include <rtl/strbuf.hxx>
69 : #include <rtl/string.hxx>
70 :
71 : using namespace ::com::sun::star::beans;
72 : using namespace ::com::sun::star::frame;
73 : using namespace ::com::sun::star::uno;
74 : using namespace ::com::sun::star::util;
75 : using namespace ::com::sun::star::frame;
76 : using namespace ::com::sun::star::lang;
77 : using namespace ::com::sun::star::system;
78 :
79 0 : class NoHelpErrorBox : public ErrorBox
80 : {
81 : public:
82 : NoHelpErrorBox( Window* _pParent );
83 :
84 : virtual void RequestHelp( const HelpEvent& rHEvt );
85 : };
86 :
87 0 : NoHelpErrorBox::NoHelpErrorBox( Window* _pParent ) :
88 :
89 0 : ErrorBox( _pParent, WB_OK, SfxResId( RID_STR_HLPFILENOTEXIST ).toString() )
90 : {
91 : // Error message: "No help available"
92 0 : }
93 :
94 0 : void NoHelpErrorBox::RequestHelp( const HelpEvent& )
95 : {
96 : // do nothing, because no help available
97 0 : }
98 :
99 : #define STARTERLIST 0
100 :
101 : static bool impl_hasHelpInstalled( const OUString &rLang );
102 :
103 : /// Return the locale we prefer for displaying help
104 72 : static OUString HelpLocaleString()
105 : {
106 72 : static OUString aLocaleStr;
107 72 : if (aLocaleStr.isEmpty())
108 : {
109 72 : const OUString aEnglish( "en" );
110 : // detect installed locale
111 72 : aLocaleStr = utl::ConfigManager::getLocale();
112 72 : bool bOk = !aLocaleStr.isEmpty();
113 72 : if ( !bOk )
114 64 : aLocaleStr = aEnglish;
115 : else
116 : {
117 8 : OUString aBaseInstallPath;
118 8 : utl::Bootstrap::locateBaseInstallation(aBaseInstallPath);
119 : static const char *szHelpPath = "/help/";
120 :
121 : OUString sHelpPath = aBaseInstallPath +
122 8 : OUString::createFromAscii(szHelpPath) + aLocaleStr;
123 8 : osl::DirectoryItem aDirItem;
124 :
125 8 : if (!osl::DirectoryItem::get(sHelpPath, aDirItem) == osl::FileBase::E_None)
126 : {
127 8 : bOk = false;
128 8 : String sLang(aLocaleStr);
129 8 : xub_StrLen nSepPos = sLang.Search( '-' );
130 8 : if (nSepPos != STRING_NOTFOUND)
131 : {
132 8 : bOk = true;
133 8 : sLang = sLang.Copy( 0, nSepPos );
134 : sHelpPath = aBaseInstallPath +
135 8 : OUString::createFromAscii(szHelpPath) + sLang;
136 8 : if (!osl::DirectoryItem::get(sHelpPath, aDirItem) == osl::FileBase::E_None)
137 0 : bOk = false;
138 8 : }
139 8 : }
140 : }
141 : // if not OK, and not even English installed, we use online help, and
142 : // have to preserve the full locale name
143 72 : if ( !bOk && impl_hasHelpInstalled( aEnglish ) )
144 0 : aLocaleStr = aEnglish;
145 : }
146 72 : return aLocaleStr;
147 : }
148 :
149 64 : void AppendConfigToken( OUStringBuffer& rURL, sal_Bool bQuestionMark, const OUString &rLang )
150 : {
151 64 : OUString aLocaleStr( rLang );
152 64 : if ( aLocaleStr.isEmpty() )
153 0 : aLocaleStr = HelpLocaleString();
154 :
155 : // query part exists?
156 64 : if ( bQuestionMark )
157 : // no, so start with '?'
158 64 : rURL.append('?');
159 : else
160 : // yes, so only append with '&'
161 0 : rURL.append('&');
162 :
163 : // set parameters
164 64 : rURL.append("Language=");
165 64 : rURL.append(aLocaleStr);
166 64 : rURL.append("&System=");
167 64 : rURL.append(SvtHelpOptions().GetSystem());
168 64 : rURL.append("&Version=");
169 64 : rURL.append(utl::ConfigManager::getProductVersion());
170 64 : }
171 :
172 0 : sal_Bool GetHelpAnchor_Impl( const OUString& _rURL, OUString& _rAnchor )
173 : {
174 0 : sal_Bool bRet = sal_False;
175 0 : OUString sAnchor;
176 :
177 : try
178 : {
179 : ::ucbhelper::Content aCnt( INetURLObject( _rURL ).GetMainURL( INetURLObject::NO_DECODE ),
180 : Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
181 0 : comphelper::getProcessComponentContext() );
182 0 : if ( ( aCnt.getPropertyValue( OUString("AnchorName") ) >>= sAnchor ) )
183 : {
184 :
185 0 : if ( !sAnchor.isEmpty() )
186 : {
187 0 : _rAnchor = String( sAnchor );
188 0 : bRet = sal_True;
189 : }
190 : }
191 : else
192 : {
193 : SAL_WARN( "sfx2.appl", "Property 'AnchorName' is missing" );
194 0 : }
195 : }
196 0 : catch (const ::com::sun::star::uno::Exception&)
197 : {
198 : }
199 :
200 0 : return bRet;
201 : }
202 :
203 : class SfxHelpOptions_Impl : public utl::ConfigItem
204 : {
205 : private:
206 : std::set < OString > m_aIds;
207 :
208 : public:
209 : SfxHelpOptions_Impl();
210 : ~SfxHelpOptions_Impl();
211 :
212 320 : bool HasId( const OString& rId ) { return m_aIds.size() ? m_aIds.find( rId ) != m_aIds.end() : false; }
213 : virtual void Notify( const com::sun::star::uno::Sequence< OUString >& aPropertyNames );
214 : virtual void Commit();
215 : };
216 :
217 40 : static Sequence< OUString > GetPropertyNames()
218 : {
219 : static const char* aPropNames[] =
220 : {
221 : "HelpAgentStarterList",
222 : };
223 :
224 40 : const int nCount = sizeof( aPropNames ) / sizeof( const char* );
225 40 : Sequence< OUString > aNames( nCount );
226 40 : OUString* pNames = aNames.getArray();
227 40 : OUString* pEnd = pNames + aNames.getLength();
228 40 : int i = 0;
229 80 : for ( ; pNames != pEnd; ++pNames )
230 40 : *pNames = OUString::createFromAscii( aPropNames[i++] );
231 :
232 40 : return aNames;
233 : }
234 :
235 40 : SfxHelpOptions_Impl::SfxHelpOptions_Impl()
236 40 : : ConfigItem( OUString("Office.SFX/Help") )
237 : {
238 40 : Sequence< OUString > aNames = GetPropertyNames();
239 40 : Sequence< Any > aValues = GetProperties( aNames );
240 40 : EnableNotification( aNames );
241 40 : const Any* pValues = aValues.getConstArray();
242 : DBG_ASSERT( aValues.getLength() == aNames.getLength(), "GetProperties failed" );
243 40 : if ( aValues.getLength() == aNames.getLength() )
244 : {
245 80 : for ( int nProp = 0; nProp < aNames.getLength(); nProp++ )
246 : {
247 : DBG_ASSERT( pValues[nProp].hasValue(), "property value missing" );
248 40 : if ( pValues[nProp].hasValue() )
249 : {
250 40 : switch ( nProp )
251 : {
252 : case STARTERLIST :
253 : {
254 40 : OUString aCodedList;
255 40 : if ( pValues[nProp] >>= aCodedList )
256 : {
257 : OString aTmp(
258 : OUStringToOString(
259 40 : aCodedList, RTL_TEXTENCODING_UTF8));
260 40 : sal_Int32 nIndex = 0;
261 2960 : do
262 : {
263 2960 : OString aToken = aTmp.getToken( 0, ',', nIndex );
264 2960 : if ( !aToken.isEmpty() )
265 2960 : m_aIds.insert( aToken );
266 : }
267 40 : while ( nIndex >= 0 );
268 : }
269 : else {
270 : SAL_WARN( "sfx2.appl", "Wrong property type!" );
271 : }
272 :
273 40 : break;
274 : }
275 :
276 : default:
277 : SAL_WARN( "sfx2.appl", "Wrong property!" );
278 0 : break;
279 : }
280 : }
281 : }
282 40 : }
283 40 : }
284 :
285 4 : SfxHelpOptions_Impl::~SfxHelpOptions_Impl()
286 : {
287 4 : }
288 :
289 :
290 0 : void SfxHelpOptions_Impl::Notify( const com::sun::star::uno::Sequence< OUString >& )
291 : {
292 0 : }
293 :
294 0 : void SfxHelpOptions_Impl::Commit()
295 : {
296 0 : }
297 :
298 : class SfxHelp_Impl
299 : {
300 : private:
301 : SfxHelpOptions_Impl* m_pOpt; // the options
302 : ::std::vector< OUString > m_aModulesList; // list of all installed modules
303 :
304 : public:
305 : SfxHelp_Impl();
306 : ~SfxHelp_Impl();
307 :
308 : SfxHelpOptions_Impl* GetOptions();
309 : static String GetHelpText( const OUString& aCommandURL, const String& rModule );
310 : };
311 :
312 72 : SfxHelp_Impl::SfxHelp_Impl() :
313 :
314 72 : m_pOpt ( NULL )
315 :
316 : {
317 72 : }
318 :
319 16 : SfxHelp_Impl::~SfxHelp_Impl()
320 : {
321 8 : delete m_pOpt;
322 8 : }
323 :
324 0 : String SfxHelp_Impl::GetHelpText( const OUString& aCommandURL, const String& rModule )
325 : {
326 : // create help url
327 0 : String aHelpURL = SfxHelp::CreateHelpURL( aCommandURL, rModule );
328 : // added 'active' parameter
329 0 : aHelpURL.Insert( String( DEFINE_CONST_UNICODE("&Active=true") ), aHelpURL.SearchBackward( '#' ) );
330 : // load help string
331 0 : return SfxContentHelper::GetActiveHelpString( aHelpURL );
332 : }
333 :
334 320 : SfxHelpOptions_Impl* SfxHelp_Impl::GetOptions()
335 : {
336 : // create if not exists
337 320 : if ( !m_pOpt )
338 40 : m_pOpt = new SfxHelpOptions_Impl;
339 320 : return m_pOpt;
340 : }
341 :
342 72 : SfxHelp::SfxHelp() :
343 :
344 : bIsDebug( sal_False ),
345 72 : pImp ( NULL )
346 :
347 : {
348 : // read the environment variable "HELP_DEBUG"
349 : // if it's set, you will see debug output on active help
350 : {
351 72 : OUString sHelpDebug;
352 72 : OUString sEnvVarName( "HELP_DEBUG" );
353 72 : osl_getEnvironment( sEnvVarName.pData, &sHelpDebug.pData );
354 72 : bIsDebug = !sHelpDebug.isEmpty();
355 : }
356 :
357 72 : pImp = new SfxHelp_Impl();
358 :
359 72 : OUString aLocaleStr = HelpLocaleString();
360 :
361 72 : sal_Int32 nSepPos = aLocaleStr.indexOf( '_' );
362 72 : if ( nSepPos != -1 )
363 : {
364 0 : aLanguageStr = aLocaleStr.copy( 0, nSepPos );
365 0 : aCountryStr = aLocaleStr.copy( nSepPos+1 );
366 : }
367 : else
368 : {
369 72 : nSepPos = aLocaleStr.indexOf( '-' );
370 72 : if ( nSepPos != -1 )
371 : {
372 8 : aLanguageStr = aLocaleStr.copy( 0, nSepPos );
373 8 : aCountryStr = aLocaleStr.copy( nSepPos+1 );
374 : }
375 : else
376 : {
377 64 : aLanguageStr = aLocaleStr;
378 : }
379 72 : }
380 72 : }
381 :
382 24 : SfxHelp::~SfxHelp()
383 : {
384 8 : delete pImp;
385 16 : }
386 :
387 0 : OUString getDefaultModule_Impl()
388 : {
389 0 : OUString sDefaultModule;
390 0 : SvtModuleOptions aModOpt;
391 0 : if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
392 0 : sDefaultModule = DEFINE_CONST_UNICODE("swriter");
393 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
394 0 : sDefaultModule = DEFINE_CONST_UNICODE("scalc");
395 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
396 0 : sDefaultModule = DEFINE_CONST_UNICODE("simpress");
397 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
398 0 : sDefaultModule = DEFINE_CONST_UNICODE("sdraw");
399 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) )
400 0 : sDefaultModule = DEFINE_CONST_UNICODE("smath");
401 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCHART ) )
402 0 : sDefaultModule = DEFINE_CONST_UNICODE("schart");
403 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SBASIC ) )
404 0 : sDefaultModule = DEFINE_CONST_UNICODE("sbasic");
405 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
406 0 : sDefaultModule = DEFINE_CONST_UNICODE("sdatabase");
407 : else
408 : {
409 : SAL_WARN( "sfx2.appl", "getDefaultModule_Impl(): no module installed" );
410 : }
411 0 : return sDefaultModule;
412 : }
413 :
414 0 : OUString getCurrentModuleIdentifier_Impl()
415 : {
416 0 : OUString sIdentifier;
417 0 : Reference < XFrame > xCurrentFrame;
418 0 : Reference < XModuleManager2 > xModuleManager( ModuleManager::create(::comphelper::getProcessComponentContext()) );
419 0 : Reference < XDesktop > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
420 0 : DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY );
421 0 : if ( xDesktop.is() )
422 0 : xCurrentFrame = xDesktop->getCurrentFrame();
423 :
424 0 : if ( xCurrentFrame.is() )
425 : {
426 : try
427 : {
428 0 : sIdentifier = xModuleManager->identify( xCurrentFrame );
429 : }
430 0 : catch (const ::com::sun::star::frame::UnknownModuleException&)
431 : {
432 : DBG_WARNING( "SfxHelp::getCurrentModuleIdentifier_Impl(): unknown module (help in help?)" );
433 : }
434 0 : catch (const Exception&)
435 : {
436 : SAL_WARN( "sfx2.appl", "SfxHelp::getCurrentModuleIdentifier_Impl(): exception of XModuleManager::identify()" );
437 : }
438 : }
439 :
440 0 : return sIdentifier;
441 : }
442 :
443 0 : OUString SfxHelp::GetHelpModuleName_Impl()
444 : {
445 0 : OUString aFactoryShortName;
446 0 : OUString aModuleIdentifier = getCurrentModuleIdentifier_Impl();
447 :
448 0 : if ( !aModuleIdentifier.isEmpty() )
449 : {
450 : try
451 : {
452 : Reference < XModuleManager2 > xModuleManager(
453 0 : ModuleManager::create(::comphelper::getProcessComponentContext()) );
454 0 : Sequence< PropertyValue > lProps;
455 0 : xModuleManager->getByName( aModuleIdentifier ) >>= lProps;
456 0 : for ( sal_Int32 i = 0; i < lProps.getLength(); ++i )
457 : {
458 0 : if ( lProps[i].Name == "ooSetupFactoryShortName" )
459 : {
460 0 : lProps[i].Value >>= aFactoryShortName;
461 0 : break;
462 : }
463 0 : }
464 : }
465 0 : catch (const Exception&)
466 : {
467 : SAL_WARN( "sfx2.appl", "SfxHelp::GetHelpModuleName_Impl(): exception of XNameAccess::getByName()" );
468 : }
469 : }
470 :
471 0 : OUString sDefaultModule = getDefaultModule_Impl();
472 0 : if ( !aFactoryShortName.isEmpty() )
473 : {
474 : // Map some module identifiers to their "real" help module string.
475 0 : if ( aFactoryShortName == "chart2" )
476 0 : aFactoryShortName = OUString( "schart" );
477 0 : else if ( aFactoryShortName == "BasicIDE" )
478 0 : aFactoryShortName = OUString( "sbasic" );
479 0 : else if ( aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("sweb"))
480 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("sglobal"))
481 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("swxform")) )
482 0 : aFactoryShortName = OUString( "swriter" );
483 0 : else if ( aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbquery"))
484 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbbrowser"))
485 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbrelation"))
486 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbtable"))
487 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbapp"))
488 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbreport"))
489 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("swreport"))
490 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbbrowser"))
491 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("swform")) )
492 0 : aFactoryShortName = OUString( "sdatabase" );
493 0 : else if ( aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("sbibliography"))
494 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("StartModule")) )
495 0 : aFactoryShortName = sDefaultModule;
496 : }
497 : else
498 0 : aFactoryShortName = sDefaultModule;
499 :
500 0 : return aFactoryShortName;
501 : }
502 :
503 0 : OUString SfxHelp::CreateHelpURL_Impl( const OUString& aCommandURL, const OUString& rModuleName )
504 : {
505 : // build up the help URL
506 0 : OUStringBuffer aHelpURL("vnd.sun.star.help://");
507 0 : sal_Bool bHasAnchor = sal_False;
508 0 : OUString aAnchor;
509 :
510 0 : OUString aModuleName( rModuleName );
511 0 : if (aModuleName.isEmpty())
512 0 : aModuleName = getDefaultModule_Impl();
513 :
514 0 : aHelpURL.append(aModuleName);
515 :
516 0 : if ( aCommandURL.isEmpty() )
517 0 : aHelpURL.append("/start");
518 : else
519 : {
520 0 : aHelpURL.append('/');
521 : aHelpURL.append(rtl::Uri::encode(aCommandURL,
522 : rtl_UriCharClassRelSegment,
523 : rtl_UriEncodeKeepEscapes,
524 0 : RTL_TEXTENCODING_UTF8));
525 :
526 0 : OUStringBuffer aTempURL = aHelpURL;
527 0 : AppendConfigToken( aTempURL, sal_True );
528 0 : bHasAnchor = GetHelpAnchor_Impl(aTempURL.makeStringAndClear(), aAnchor);
529 : }
530 :
531 0 : AppendConfigToken( aHelpURL, sal_True );
532 :
533 0 : if ( bHasAnchor )
534 : {
535 0 : aHelpURL.append('#');
536 0 : aHelpURL.append(aAnchor);
537 : }
538 :
539 0 : return aHelpURL.makeStringAndClear();
540 : }
541 :
542 0 : SfxHelpWindow_Impl* impl_createHelp(Reference< XFrame >& rHelpTask ,
543 : Reference< XFrame >& rHelpContent)
544 : {
545 0 : Reference < XFrame > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
546 0 : DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY );
547 :
548 : // otherwhise - create new help task
549 0 : Reference< XFrame > xHelpTask = xDesktop->findFrame(
550 : OUString("OFFICE_HELP_TASK"),
551 0 : FrameSearchFlag::TASKS | FrameSearchFlag::CREATE);
552 0 : if (!xHelpTask.is())
553 0 : return 0;
554 :
555 : // create all internal windows and sub frames ...
556 0 : Reference< ::com::sun::star::awt::XWindow > xParentWindow = xHelpTask->getContainerWindow();
557 0 : Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow );
558 0 : SfxHelpWindow_Impl* pHelpWindow = new SfxHelpWindow_Impl( xHelpTask, pParentWindow, WB_DOCKBORDER );
559 0 : Reference< ::com::sun::star::awt::XWindow > xHelpWindow = VCLUnoHelper::GetInterface( pHelpWindow );
560 :
561 0 : Reference< XFrame > xHelpContent;
562 0 : if (xHelpTask->setComponent( xHelpWindow, Reference< XController >() ))
563 : {
564 : // Customize UI ...
565 0 : xHelpTask->setName( OUString("OFFICE_HELP_TASK") );
566 :
567 0 : Reference< XPropertySet > xProps(xHelpTask, UNO_QUERY);
568 0 : if (xProps.is())
569 0 : xProps->setPropertyValue(
570 : DEFINE_CONST_UNICODE("Title"),
571 0 : makeAny(SfxResId(STR_HELP_WINDOW_TITLE).toString()));
572 :
573 0 : pHelpWindow->setContainerWindow( xParentWindow );
574 0 : xParentWindow->setVisible(sal_True);
575 0 : xHelpWindow->setVisible(sal_True);
576 :
577 : // This sub frame is created internaly (if we called new SfxHelpWindow_Impl() ...)
578 : // It should exist :-)
579 0 : xHelpContent = xHelpTask->findFrame(OUString("OFFICE_HELP"), FrameSearchFlag::CHILDREN);
580 : }
581 :
582 0 : if (!xHelpContent.is())
583 0 : delete pHelpWindow;
584 :
585 0 : xHelpContent->setName(OUString("OFFICE_HELP"));
586 :
587 0 : rHelpTask = xHelpTask;
588 0 : rHelpContent = xHelpContent;
589 0 : return pHelpWindow;
590 : }
591 :
592 0 : OUString SfxHelp::GetHelpText( const OUString& aCommandURL, const Window* pWindow )
593 : {
594 0 : OUString sModuleName = GetHelpModuleName_Impl();
595 0 : OUString sHelpText = pImp->GetHelpText( aCommandURL, sModuleName );
596 :
597 0 : OString aNewHelpId;
598 :
599 0 : if (pWindow && sHelpText.isEmpty())
600 : {
601 : // no help text found -> try with parent help id.
602 0 : Window* pParent = pWindow->GetParent();
603 0 : while ( pParent )
604 : {
605 0 : aNewHelpId = pParent->GetHelpId();
606 0 : sHelpText = pImp->GetHelpText( OStringToOUString(aNewHelpId, RTL_TEXTENCODING_UTF8), sModuleName );
607 0 : if (!sHelpText.isEmpty())
608 0 : pParent = NULL;
609 : else
610 0 : pParent = pParent->GetParent();
611 : }
612 :
613 0 : if (bIsDebug && sHelpText.isEmpty())
614 0 : aNewHelpId = OString();
615 : }
616 :
617 : // add some debug information?
618 0 : if ( bIsDebug )
619 : {
620 0 : sHelpText += DEFINE_CONST_UNICODE("\n-------------\n");
621 0 : sHelpText += String( sModuleName );
622 0 : sHelpText += DEFINE_CONST_UNICODE(": ");
623 0 : sHelpText += aCommandURL;
624 0 : if ( !aNewHelpId.isEmpty() )
625 : {
626 0 : sHelpText += DEFINE_CONST_UNICODE(" - ");
627 0 : sHelpText += String(OStringToOUString(aNewHelpId, RTL_TEXTENCODING_UTF8));
628 : }
629 : }
630 :
631 0 : return sHelpText;
632 : }
633 :
634 : /// Check for built-in help
635 64 : static bool impl_hasHelpInstalled( const OUString &rLang = OUString() )
636 : {
637 64 : OUStringBuffer aHelpRootURL("vnd.sun.star.help://");
638 64 : AppendConfigToken(aHelpRootURL, sal_True, rLang);
639 64 : Sequence< OUString > aFactories = SfxContentHelper::GetResultSet(aHelpRootURL.makeStringAndClear());
640 :
641 64 : return ( aFactories.getLength() != 0 );
642 : }
643 :
644 0 : sal_Bool SfxHelp::SearchKeyword( const OUString& rKeyword )
645 : {
646 0 : return Start_Impl( String(), NULL, rKeyword );
647 : }
648 :
649 0 : sal_Bool SfxHelp::Start( const OUString& rURL, const Window* pWindow )
650 : {
651 0 : return Start_Impl( rURL, pWindow, OUString() );
652 : }
653 :
654 : /// Redirect the vnd.sun.star.help:// urls to http://help.libreoffice.org
655 0 : static bool impl_showOnlineHelp( const String& rURL )
656 : {
657 0 : String aInternal( "vnd.sun.star.help://" );
658 0 : if ( rURL.Len() <= aInternal.Len() || rURL.Copy( 0, aInternal.Len() ) != aInternal )
659 0 : return false;
660 :
661 0 : OUString aHelpLink( "http://help.libreoffice.org/" );
662 0 : aHelpLink += rURL.Copy( aInternal.Len() );
663 : try
664 : {
665 : Reference< XSystemShellExecute > xSystemShell(
666 0 : SystemShellExecute::create(::comphelper::getProcessComponentContext()) );
667 :
668 0 : xSystemShell->execute( aHelpLink, OUString(), SystemShellExecuteFlags::URIS_ONLY );
669 0 : return true;
670 : }
671 0 : catch (const Exception&)
672 : {
673 : }
674 0 : return false;
675 : }
676 :
677 0 : sal_Bool SfxHelp::Start_Impl(const OUString& rURL, const Window* pWindow, const OUString& rKeyword)
678 : {
679 0 : OUStringBuffer aHelpRootURL("vnd.sun.star.help://");
680 0 : AppendConfigToken(aHelpRootURL, sal_True);
681 0 : Sequence< OUString > aFactories = SfxContentHelper::GetResultSet(aHelpRootURL.makeStringAndClear());
682 :
683 : /* rURL may be
684 : - a "real" URL
685 : - a HelpID (formerly a long, now a string)
686 : If rURL is a URL, CreateHelpURL should be called for this URL
687 : If rURL is an arbitrary string, the same should happen, but the URL should be tried out
688 : if it delivers real help content. In case only the Help Error Document is returned, the
689 : parent of the window for that help was called, is asked for its HelpID.
690 : For compatibility reasons this upward search is not implemented for "real" URLs.
691 : Help keyword search now is implemented as own method; in former versions it
692 : was done via Help::Start, but this implementation conflicted with the upward search.
693 : */
694 0 : String aHelpURL;
695 0 : INetURLObject aParser( rURL );
696 0 : INetProtocol nProtocol = aParser.GetProtocol();
697 0 : String aHelpModuleName( GetHelpModuleName_Impl() );
698 :
699 0 : switch ( nProtocol )
700 : {
701 : case INET_PROT_VND_SUN_STAR_HELP:
702 : // already a vnd.sun.star.help URL -> nothing to do
703 0 : aHelpURL = rURL;
704 0 : break;
705 : default:
706 : {
707 : // no URL, just a HelpID (maybe empty in case of keyword search)
708 0 : aHelpURL = CreateHelpURL_Impl( rURL, aHelpModuleName );
709 :
710 0 : if ( impl_hasHelpInstalled() && pWindow && SfxContentHelper::IsHelpErrorDocument( aHelpURL ) )
711 : {
712 : // no help found -> try with parent help id.
713 0 : Window* pParent = pWindow->GetParent();
714 0 : while ( pParent )
715 : {
716 0 : OString aHelpId = pParent->GetHelpId();
717 0 : aHelpURL = CreateHelpURL( OStringToOUString(aHelpId, RTL_TEXTENCODING_UTF8), aHelpModuleName );
718 0 : if ( !SfxContentHelper::IsHelpErrorDocument( aHelpURL ) )
719 : {
720 : break;
721 : }
722 : else
723 : {
724 0 : pParent = pParent->GetParent();
725 0 : if ( !pParent )
726 : {
727 : // create help url of start page ( helpid == 0 -> start page)
728 0 : aHelpURL = CreateHelpURL( String(), aHelpModuleName );
729 : }
730 : }
731 0 : }
732 : }
733 0 : break;
734 : }
735 : }
736 :
737 0 : if ( !impl_hasHelpInstalled() )
738 : {
739 0 : if ( impl_showOnlineHelp( aHelpURL ) )
740 0 : return sal_True;
741 : else
742 : {
743 0 : NoHelpErrorBox aErrBox( const_cast< Window* >( pWindow ) );
744 0 : aErrBox.Execute();
745 0 : return sal_False;
746 : }
747 : }
748 :
749 0 : Reference < XFrame > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
750 0 : DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY );
751 :
752 : // check if help window is still open
753 : // If not, create a new one and return access directly to the internal sub frame showing the help content
754 : // search must be done here; search one desktop level could return an arbitraty frame
755 0 : Reference< XFrame > xHelp = xDesktop->findFrame(
756 : OUString("OFFICE_HELP_TASK"),
757 0 : FrameSearchFlag::CHILDREN);
758 0 : Reference< XFrame > xHelpContent = xDesktop->findFrame(
759 : OUString("OFFICE_HELP"),
760 0 : FrameSearchFlag::CHILDREN);
761 :
762 0 : SfxHelpWindow_Impl* pHelpWindow = 0;
763 0 : if (!xHelp.is())
764 0 : pHelpWindow = impl_createHelp(xHelp, xHelpContent);
765 : else
766 0 : pHelpWindow = (SfxHelpWindow_Impl*)VCLUnoHelper::GetWindow(xHelp->getComponentWindow());
767 0 : if (!xHelp.is() || !xHelpContent.is() || !pHelpWindow)
768 0 : return sal_False;
769 :
770 : #ifdef DBG_UTIL
771 : OStringBuffer aTmp(RTL_CONSTASCII_STRINGPARAM("SfxHelp: HelpId = "));
772 : aTmp.append(OUStringToOString(aHelpURL, RTL_TEXTENCODING_UTF8));
773 : OSL_TRACE( aTmp.getStr() );
774 : #endif
775 :
776 0 : pHelpWindow->SetHelpURL( aHelpURL );
777 0 : pHelpWindow->loadHelpContent(aHelpURL);
778 0 : if (!rKeyword.isEmpty())
779 0 : pHelpWindow->OpenKeyword( rKeyword );
780 :
781 0 : Reference < ::com::sun::star::awt::XTopWindow > xTopWindow( xHelp->getContainerWindow(), UNO_QUERY );
782 0 : if ( xTopWindow.is() )
783 0 : xTopWindow->toFront();
784 :
785 0 : return sal_True;
786 : }
787 :
788 0 : OUString SfxHelp::CreateHelpURL(const OUString& aCommandURL, const OUString& rModuleName)
789 : {
790 0 : SfxHelp* pHelp = static_cast< SfxHelp* >(Application::GetHelp());
791 0 : return pHelp ? pHelp->CreateHelpURL_Impl( aCommandURL, rModuleName ) : OUString();
792 : }
793 :
794 320 : void SfxHelp::OpenHelpAgent( SfxFrame*, const OString& sHelpId )
795 : {
796 320 : SfxHelp* pHelp = (static_cast< SfxHelp* >(Application::GetHelp()) );
797 320 : if ( pHelp )
798 320 : pHelp->OpenHelpAgent( sHelpId );
799 320 : }
800 :
801 320 : void SfxHelp::OpenHelpAgent( const OString& sHelpId )
802 : {
803 320 : if ( SvtHelpOptions().IsHelpAgentAutoStartMode() )
804 : {
805 320 : SfxHelpOptions_Impl *pOpt = pImp->GetOptions();
806 320 : if ( !pOpt->HasId( sHelpId ) )
807 640 : return;
808 :
809 : try
810 : {
811 0 : URL aURL;
812 0 : aURL.Complete = CreateHelpURL_Impl( OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), GetHelpModuleName_Impl() );
813 0 : Reference< XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
814 0 : xTrans->parseStrict(aURL);
815 :
816 0 : Reference < XFrame > xCurrentFrame;
817 0 : Reference < XDesktop > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
818 0 : DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY );
819 0 : if ( xDesktop.is() )
820 0 : xCurrentFrame = xDesktop->getCurrentFrame();
821 :
822 0 : Reference< XDispatchProvider > xDispProv( xCurrentFrame, UNO_QUERY );
823 0 : Reference< XDispatch > xHelpDispatch;
824 0 : if ( xDispProv.is() )
825 0 : xHelpDispatch = xDispProv->queryDispatch(
826 : aURL, OUString("_helpagent"),
827 0 : FrameSearchFlag::PARENT | FrameSearchFlag::SELF );
828 :
829 : DBG_ASSERT( xHelpDispatch.is(), "OpenHelpAgent: could not get a dispatcher!" );
830 0 : if ( xHelpDispatch.is() )
831 0 : xHelpDispatch->dispatch( aURL, Sequence< PropertyValue >() );
832 : }
833 0 : catch (const Exception&)
834 : {
835 : SAL_WARN( "sfx2.appl", "OpenHelpAgent: caught an exception while executing the dispatch!" );
836 : }
837 : }
838 : }
839 :
840 0 : OUString SfxHelp::GetDefaultHelpModule()
841 : {
842 0 : return getDefaultModule_Impl();
843 : }
844 :
845 0 : OUString SfxHelp::GetCurrentModuleIdentifier()
846 : {
847 0 : return getCurrentModuleIdentifier_Impl();
848 : }
849 :
850 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|