1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "sfx2/sfxhelp.hxx"
33 #include <com/sun/star/uno/Reference.h>
34 #include <com/sun/star/frame/XFrame.hpp>
35 #include <com/sun/star/frame/XComponentLoader.hpp>
36 #include <com/sun/star/lang/XComponent.hpp>
37 #include <comphelper/processfactory.hxx>
38 #include <com/sun/star/awt/XWindow.hpp>
39 #include <com/sun/star/awt/XTopWindow.hpp>
40 #include <com/sun/star/awt/PosSize.hpp>
41 #include <com/sun/star/frame/XDesktop.hpp>
42 #include <com/sun/star/util/XURLTransformer.hpp>
43 #include <com/sun/star/frame/XDispatch.hpp>
44 #include <com/sun/star/frame/XDispatchProvider.hpp>
45 #include <com/sun/star/container/XNameAccess.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/frame/FrameSearchFlag.hpp>
48 #include <toolkit/helper/vclunohelper.hxx>
49 #include <com/sun/star/frame/XModuleManager.hpp>
50 #include <com/sun/star/system/XSystemShellExecute.hpp>
51 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
52 #include <unotools/configmgr.hxx>
53 #include <unotools/configitem.hxx>
54 #include <svtools/helpopt.hxx>
55 #include <unotools/moduleoptions.hxx>
56 #include <tools/urlobj.hxx>
57 #include <ucbhelper/content.hxx>
58 #include <unotools/pathoptions.hxx>
59 #include <rtl/ustring.hxx>
60 #include <osl/process.h>
61 #include <osl/file.hxx>
62 #include <unotools/bootstrap.hxx>
63 #include <rtl/uri.hxx>
64 #include <vcl/msgbox.hxx>
65 #include <svtools/ehdl.hxx>
66 #include <svtools/sfxecode.hxx>
67 #include <svl/svstdarr.hxx>
69 #include "newhelp.hxx"
70 #include <sfx2/objsh.hxx>
71 #include <sfx2/docfac.hxx>
72 #include "sfx2/sfxresid.hxx"
75 #include <sfx2/sfxuno.hxx>
76 #include <vcl/svapp.hxx>
77 #include <sfx2/frame.hxx>
78 #include <rtl/strbuf.hxx>
79 #include <rtl/string.hxx>
81 using namespace ::com::sun::star::beans
;
82 using namespace ::com::sun::star::frame
;
83 using namespace ::com::sun::star::uno
;
84 using namespace ::com::sun::star::util
;
85 using namespace ::com::sun::star::frame
;
86 using namespace ::com::sun::star::lang
;
87 using namespace ::com::sun::star::system
;
89 class NoHelpErrorBox
: public ErrorBox
92 NoHelpErrorBox( Window
* _pParent
);
94 virtual void RequestHelp( const HelpEvent
& rHEvt
);
97 NoHelpErrorBox::NoHelpErrorBox( Window
* _pParent
) :
99 ErrorBox( _pParent
, WB_OK
, String( SfxResId( RID_STR_HLPFILENOTEXIST
) ) )
101 // Error message: "No help available"
104 void NoHelpErrorBox::RequestHelp( const HelpEvent
& )
106 // do nothing, because no help available
109 #define STARTERLIST 0
111 static bool impl_hasHelpInstalled( const rtl::OUString
&rLang
);
113 /// Return the locale we prefer for displaying help
114 static rtl::OUString
HelpLocaleString()
116 static rtl::OUString aLocaleStr
;
117 if (aLocaleStr
.isEmpty())
119 const rtl::OUString
aEnglish( "en" );
120 // detect installed locale
121 aLocaleStr
= utl::ConfigManager::getLocale();
122 bool bOk
= !aLocaleStr
.isEmpty();
124 aLocaleStr
= aEnglish
;
127 rtl::OUString aBaseInstallPath
;
128 utl::Bootstrap::locateBaseInstallation(aBaseInstallPath
);
129 static const char *szHelpPath
= "/help/";
131 rtl::OUString sHelpPath
= aBaseInstallPath
+
132 rtl::OUString::createFromAscii(szHelpPath
) + aLocaleStr
;
133 osl::DirectoryItem aDirItem
;
135 if (!osl::DirectoryItem::get(sHelpPath
, aDirItem
) == osl::FileBase::E_None
)
138 String
sLang(aLocaleStr
);
139 xub_StrLen nSepPos
= sLang
.Search( '-' );
140 if (nSepPos
!= STRING_NOTFOUND
)
143 sLang
= sLang
.Copy( 0, nSepPos
);
144 sHelpPath
= aBaseInstallPath
+
145 rtl::OUString::createFromAscii(szHelpPath
) + sLang
;
146 if (!osl::DirectoryItem::get(sHelpPath
, aDirItem
) == osl::FileBase::E_None
)
151 // if not OK, and not even English installed, we use online help, and
152 // have to preserve the full locale name
153 if ( !bOk
&& impl_hasHelpInstalled( aEnglish
) )
154 aLocaleStr
= aEnglish
;
159 void AppendConfigToken( String
& rURL
, sal_Bool bQuestionMark
, const rtl::OUString
&rLang
)
161 ::rtl::OUString
aLocaleStr( rLang
);
162 if ( aLocaleStr
.isEmpty() )
163 aLocaleStr
= HelpLocaleString();
165 // query part exists?
167 // no, so start with '?'
170 // yes, so only append with '&'
174 rURL
+= DEFINE_CONST_UNICODE("Language=");
175 rURL
+= String( aLocaleStr
);
176 rURL
+= DEFINE_CONST_UNICODE("&System=");
177 rURL
+= SvtHelpOptions().GetSystem();
178 rURL
+= DEFINE_CONST_UNICODE("&Version=");
179 rURL
+= utl::ConfigManager::getProductVersion();
182 sal_Bool
GetHelpAnchor_Impl( const String
& _rURL
, String
& _rAnchor
)
184 sal_Bool bRet
= sal_False
;
185 ::rtl::OUString sAnchor
;
189 ::ucbhelper::Content
aCnt( INetURLObject( _rURL
).GetMainURL( INetURLObject::NO_DECODE
),
190 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> () );
191 if ( ( aCnt
.getPropertyValue( ::rtl::OUString("AnchorName") ) >>= sAnchor
) )
194 if ( !sAnchor
.isEmpty() )
196 _rAnchor
= String( sAnchor
);
202 SAL_WARN( "sfx2.appl", "Property 'AnchorName' is missing" );
205 catch (const ::com::sun::star::uno::Exception
&)
212 class SfxHelpOptions_Impl
: public utl::ConfigItem
215 std::set
< rtl::OString
> m_aIds
;
218 SfxHelpOptions_Impl();
219 ~SfxHelpOptions_Impl();
221 bool HasId( const rtl::OString
& rId
) { return m_aIds
.size() ? m_aIds
.find( rId
) != m_aIds
.end() : false; }
222 virtual void Notify( const com::sun::star::uno::Sequence
< rtl::OUString
>& aPropertyNames
);
223 virtual void Commit();
226 static Sequence
< ::rtl::OUString
> GetPropertyNames()
228 static const char* aPropNames
[] =
230 "HelpAgentStarterList",
233 const int nCount
= sizeof( aPropNames
) / sizeof( const char* );
234 Sequence
< ::rtl::OUString
> aNames( nCount
);
235 ::rtl::OUString
* pNames
= aNames
.getArray();
236 ::rtl::OUString
* pEnd
= pNames
+ aNames
.getLength();
238 for ( ; pNames
!= pEnd
; ++pNames
)
239 *pNames
= ::rtl::OUString::createFromAscii( aPropNames
[i
++] );
244 SfxHelpOptions_Impl::SfxHelpOptions_Impl()
245 : ConfigItem( ::rtl::OUString("Office.SFX/Help") )
247 Sequence
< ::rtl::OUString
> aNames
= GetPropertyNames();
248 Sequence
< Any
> aValues
= GetProperties( aNames
);
249 EnableNotification( aNames
);
250 const Any
* pValues
= aValues
.getConstArray();
251 DBG_ASSERT( aValues
.getLength() == aNames
.getLength(), "GetProperties failed" );
252 if ( aValues
.getLength() == aNames
.getLength() )
254 for ( int nProp
= 0; nProp
< aNames
.getLength(); nProp
++ )
256 DBG_ASSERT( pValues
[nProp
].hasValue(), "property value missing" );
257 if ( pValues
[nProp
].hasValue() )
263 ::rtl::OUString aCodedList
;
264 if ( pValues
[nProp
] >>= aCodedList
)
267 rtl::OUStringToOString(
268 aCodedList
, RTL_TEXTENCODING_UTF8
) );
269 sal_Int32 nIndex
= 0;
272 rtl::OString aToken
= aTmp
.getToken( 0, ',', nIndex
);
273 if ( !aToken
.isEmpty() )
274 m_aIds
.insert( aToken
);
276 while ( nIndex
>= 0 );
279 SAL_WARN( "sfx2.appl", "Wrong property type!" );
286 SAL_WARN( "sfx2.appl", "Wrong property!" );
294 SfxHelpOptions_Impl::~SfxHelpOptions_Impl()
299 void SfxHelpOptions_Impl::Notify( const com::sun::star::uno::Sequence
< rtl::OUString
>& )
303 void SfxHelpOptions_Impl::Commit()
310 sal_Bool m_bIsDebug
; // environment variable "help_debug=1"
311 SfxHelpOptions_Impl
* m_pOpt
; // the options
312 ::std::vector
< ::rtl::OUString
> m_aModulesList
; // list of all installed modules
315 SfxHelp_Impl( sal_Bool bDebug
);
318 SfxHelpOptions_Impl
* GetOptions();
319 static String
GetHelpText( const rtl::OUString
& aCommandURL
, const String
& rModule
);
322 SfxHelp_Impl::SfxHelp_Impl( sal_Bool bDebug
) :
324 m_bIsDebug ( bDebug
),
330 SfxHelp_Impl::~SfxHelp_Impl()
335 String
SfxHelp_Impl::GetHelpText( const rtl::OUString
& aCommandURL
, const String
& rModule
)
338 String aHelpURL
= SfxHelp::CreateHelpURL( aCommandURL
, rModule
);
339 // added 'active' parameter
340 aHelpURL
.Insert( String( DEFINE_CONST_UNICODE("&Active=true") ), aHelpURL
.SearchBackward( '#' ) );
342 return SfxContentHelper::GetActiveHelpString( aHelpURL
);
345 SfxHelpOptions_Impl
* SfxHelp_Impl::GetOptions()
347 // create if not exists
349 m_pOpt
= new SfxHelpOptions_Impl
;
355 bIsDebug( sal_False
),
359 // read the environment variable "HELP_DEBUG"
360 // if it's set, you will see debug output on active help
362 ::rtl::OUString sHelpDebug
;
363 ::rtl::OUString
sEnvVarName( "HELP_DEBUG" );
364 osl_getEnvironment( sEnvVarName
.pData
, &sHelpDebug
.pData
);
365 bIsDebug
= !sHelpDebug
.isEmpty();
368 pImp
= new SfxHelp_Impl( bIsDebug
);
370 ::rtl::OUString aLocaleStr
= HelpLocaleString();
372 sal_Int32 nSepPos
= aLocaleStr
.indexOf( '_' );
375 aLanguageStr
= aLocaleStr
.copy( 0, nSepPos
);
376 aCountryStr
= aLocaleStr
.copy( nSepPos
+1 );
380 nSepPos
= aLocaleStr
.indexOf( '-' );
383 aLanguageStr
= aLocaleStr
.copy( 0, nSepPos
);
384 aCountryStr
= aLocaleStr
.copy( nSepPos
+1 );
388 aLanguageStr
= aLocaleStr
;
398 ::rtl::OUString
getDefaultModule_Impl()
400 rtl::OUString sDefaultModule
;
401 SvtModuleOptions aModOpt
;
402 if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
403 sDefaultModule
= DEFINE_CONST_UNICODE("swriter");
404 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SCALC
) )
405 sDefaultModule
= DEFINE_CONST_UNICODE("scalc");
406 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS
) )
407 sDefaultModule
= DEFINE_CONST_UNICODE("simpress");
408 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SDRAW
) )
409 sDefaultModule
= DEFINE_CONST_UNICODE("sdraw");
410 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SMATH
) )
411 sDefaultModule
= DEFINE_CONST_UNICODE("smath");
412 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SCHART
) )
413 sDefaultModule
= DEFINE_CONST_UNICODE("schart");
414 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SBASIC
) )
415 sDefaultModule
= DEFINE_CONST_UNICODE("sbasic");
416 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SDATABASE
) )
417 sDefaultModule
= DEFINE_CONST_UNICODE("sdatabase");
420 SAL_WARN( "sfx2.appl", "getDefaultModule_Impl(): no module installed" );
422 return sDefaultModule
;
425 ::rtl::OUString
getCurrentModuleIdentifier_Impl()
427 ::rtl::OUString sIdentifier
;
428 Reference
< XFrame
> xCurrentFrame
;
429 Reference
< XModuleManager
> xModuleManager( ::comphelper::getProcessServiceFactory()->createInstance(
430 DEFINE_CONST_UNICODE("com.sun.star.frame.ModuleManager") ), UNO_QUERY
);
431 Reference
< XDesktop
> xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
432 DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY
);
434 xCurrentFrame
= xDesktop
->getCurrentFrame();
436 if ( xCurrentFrame
.is() && xModuleManager
.is() )
440 sIdentifier
= xModuleManager
->identify( xCurrentFrame
);
442 catch (const ::com::sun::star::frame::UnknownModuleException
&)
444 DBG_WARNING( "SfxHelp::getCurrentModuleIdentifier_Impl(): unknown module (help in help?)" );
446 catch (const Exception
&)
448 SAL_WARN( "sfx2.appl", "SfxHelp::getCurrentModuleIdentifier_Impl(): exception of XModuleManager::identify()" );
455 String
SfxHelp::GetHelpModuleName_Impl()
458 rtl::OUString aFactoryShortName
;
459 rtl::OUString aModuleIdentifier
= getCurrentModuleIdentifier_Impl();
461 if ( !aModuleIdentifier
.isEmpty() )
465 Reference
< XModuleManager
> xModuleManager(
466 ::comphelper::getProcessServiceFactory()->createInstance(
467 DEFINE_CONST_UNICODE("com.sun.star.frame.ModuleManager") ), UNO_QUERY
);
468 Sequence
< PropertyValue
> lProps
;
469 Reference
< ::com::sun::star::container::XNameAccess
> xCont( xModuleManager
, UNO_QUERY
);
471 xCont
->getByName( aModuleIdentifier
) >>= lProps
;
472 for ( sal_Int32 i
= 0; i
< lProps
.getLength(); ++i
)
474 if ( lProps
[i
].Name
== "ooSetupFactoryShortName" )
476 lProps
[i
].Value
>>= aFactoryShortName
;
481 catch (const Exception
&)
483 SAL_WARN( "sfx2.appl", "SfxHelp::GetHelpModuleName_Impl(): exception of XNameAccess::getByName()" );
487 rtl::OUString sDefaultModule
= getDefaultModule_Impl();
488 if ( !aFactoryShortName
.isEmpty() )
490 // Map some module identifiers to their "real" help module string.
491 if ( aFactoryShortName
== "chart2" )
492 aFactoryShortName
= rtl::OUString( "schart" );
493 else if ( aFactoryShortName
== "BasicIDE" )
494 aFactoryShortName
= rtl::OUString( "sbasic" );
495 else if ( aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("sweb"))
496 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("sglobal"))
497 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("swxform")) )
498 aFactoryShortName
= rtl::OUString( "swriter" );
499 else if ( aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbquery"))
500 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbbrowser"))
501 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbrelation"))
502 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbtable"))
503 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbapp"))
504 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbreport"))
505 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("swreport"))
506 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbbrowser"))
507 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("swform")) )
508 aFactoryShortName
= rtl::OUString( "sdatabase" );
509 else if ( aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("sbibliography"))
510 || aFactoryShortName
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("StartModule")) )
511 aFactoryShortName
= sDefaultModule
;
514 aFactoryShortName
= sDefaultModule
;
516 sModuleName
= String( aFactoryShortName
);
520 String
SfxHelp::CreateHelpURL_Impl( const String
& aCommandURL
, const String
& rModuleName
)
522 // build up the help URL
524 sal_Bool bHasAnchor
= sal_False
;
527 String
aModuleName( rModuleName
);
528 if ( aModuleName
.Len() == 0 )
529 aModuleName
= getDefaultModule_Impl();
531 aHelpURL
= String::CreateFromAscii("vnd.sun.star.help://");
532 aHelpURL
+= aModuleName
;
534 if ( !aCommandURL
.Len() )
535 aHelpURL
+= String::CreateFromAscii("/start");
539 aHelpURL
+= String( rtl::Uri::encode( aCommandURL
,
540 rtl_UriCharClassRelSegment
,
541 rtl_UriEncodeKeepEscapes
,
542 RTL_TEXTENCODING_UTF8
));
544 String aTempURL
= aHelpURL
;
545 AppendConfigToken( aTempURL
, sal_True
);
546 bHasAnchor
= GetHelpAnchor_Impl( aTempURL
, aAnchor
);
549 AppendConfigToken( aHelpURL
, sal_True
);
560 SfxHelpWindow_Impl
* impl_createHelp(Reference
< XFrame
>& rHelpTask
,
561 Reference
< XFrame
>& rHelpContent
)
563 Reference
< XFrame
> xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
564 DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY
);
566 // otherwhise - create new help task
567 Reference
< XFrame
> xHelpTask
= xDesktop
->findFrame(
568 ::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP_TASK")),
569 FrameSearchFlag::TASKS
| FrameSearchFlag::CREATE
);
573 // create all internal windows and sub frames ...
574 Reference
< ::com::sun::star::awt::XWindow
> xParentWindow
= xHelpTask
->getContainerWindow();
575 Window
* pParentWindow
= VCLUnoHelper::GetWindow( xParentWindow
);
576 SfxHelpWindow_Impl
* pHelpWindow
= new SfxHelpWindow_Impl( xHelpTask
, pParentWindow
, WB_DOCKBORDER
);
577 Reference
< ::com::sun::star::awt::XWindow
> xHelpWindow
= VCLUnoHelper::GetInterface( pHelpWindow
);
579 Reference
< XFrame
> xHelpContent
;
580 if (xHelpTask
->setComponent( xHelpWindow
, Reference
< XController
>() ))
583 xHelpTask
->setName( ::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP_TASK")) );
585 Reference
< XPropertySet
> xProps(xHelpTask
, UNO_QUERY
);
587 xProps
->setPropertyValue(
588 DEFINE_CONST_UNICODE("Title"),
589 makeAny(::rtl::OUString(String(SfxResId(STR_HELP_WINDOW_TITLE
)))));
591 pHelpWindow
->setContainerWindow( xParentWindow
);
592 xParentWindow
->setVisible(sal_True
);
593 xHelpWindow
->setVisible(sal_True
);
595 // This sub frame is created internaly (if we called new SfxHelpWindow_Impl() ...)
596 // It should exist :-)
597 xHelpContent
= xHelpTask
->findFrame(::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP")), FrameSearchFlag::CHILDREN
);
600 if (!xHelpContent
.is())
603 xHelpContent
->setName(::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP")));
605 rHelpTask
= xHelpTask
;
606 rHelpContent
= xHelpContent
;
610 XubString
SfxHelp::GetHelpText( const String
& aCommandURL
, const Window
* pWindow
)
612 String sModuleName
= GetHelpModuleName_Impl();
613 String sHelpText
= pImp
->GetHelpText( aCommandURL
, sModuleName
);
615 rtl::OString aNewHelpId
;
617 if ( pWindow
&& !sHelpText
.Len() )
619 // no help text found -> try with parent help id.
620 Window
* pParent
= pWindow
->GetParent();
623 aNewHelpId
= pParent
->GetHelpId();
624 sHelpText
= pImp
->GetHelpText( rtl::OStringToOUString(aNewHelpId
, RTL_TEXTENCODING_UTF8
), sModuleName
);
625 if ( sHelpText
.Len() > 0 )
628 pParent
= pParent
->GetParent();
631 if ( bIsDebug
&& !sHelpText
.Len() )
632 aNewHelpId
= rtl::OString();
635 // add some debug information?
638 sHelpText
+= DEFINE_CONST_UNICODE("\n-------------\n");
639 sHelpText
+= String( sModuleName
);
640 sHelpText
+= DEFINE_CONST_UNICODE(": ");
641 sHelpText
+= aCommandURL
;
642 if ( !aNewHelpId
.isEmpty() )
644 sHelpText
+= DEFINE_CONST_UNICODE(" - ");
645 sHelpText
+= String(rtl::OStringToOUString(aNewHelpId
, RTL_TEXTENCODING_UTF8
));
652 /// Check for built-in help
653 static bool impl_hasHelpInstalled( const rtl::OUString
&rLang
= rtl::OUString() )
655 String
aHelpRootURL( DEFINE_CONST_OUSTRING("vnd.sun.star.help://") );
656 AppendConfigToken( aHelpRootURL
, sal_True
, rLang
);
657 Sequence
< ::rtl::OUString
> aFactories
= SfxContentHelper::GetResultSet( aHelpRootURL
);
659 return ( aFactories
.getLength() != 0 );
662 sal_Bool
SfxHelp::SearchKeyword( const XubString
& rKeyword
)
664 return Start_Impl( String(), NULL
, rKeyword
);
667 sal_Bool
SfxHelp::Start( const String
& rURL
, const Window
* pWindow
)
669 return Start_Impl( rURL
, pWindow
, String() );
672 /// Redirect the vnd.sun.star.help:// urls to http://help.libreoffice.org
673 static bool impl_showOnlineHelp( const String
& rURL
)
675 String
aInternal( "vnd.sun.star.help://" );
676 if ( rURL
.Len() <= aInternal
.Len() || rURL
.Copy( 0, aInternal
.Len() ) != aInternal
)
679 rtl::OUString
aHelpLink( "http://help.libreoffice.org/" );
680 aHelpLink
+= rURL
.Copy( aInternal
.Len() );
683 Reference
< XSystemShellExecute
> xSystemShell(
684 ::comphelper::getProcessServiceFactory()->createInstance(
685 rtl::OUString( "com.sun.star.system.SystemShellExecute" ) ),
688 if ( xSystemShell
.is() )
690 xSystemShell
->execute( aHelpLink
, rtl::OUString(), SystemShellExecuteFlags::URIS_ONLY
);
694 catch (const Exception
&)
700 sal_Bool
SfxHelp::Start_Impl( const String
& rURL
, const Window
* pWindow
, const String
& rKeyword
)
702 String
aHelpRootURL( DEFINE_CONST_OUSTRING("vnd.sun.star.help://") );
703 AppendConfigToken( aHelpRootURL
, sal_True
);
704 Sequence
< ::rtl::OUString
> aFactories
= SfxContentHelper::GetResultSet( aHelpRootURL
);
708 - a HelpID (formerly a long, now a string)
709 If rURL is a URL, CreateHelpURL should be called for this URL
710 If rURL is an arbitrary string, the same should happen, but the URL should be tried out
711 if it delivers real help content. In case only the Help Error Document is returned, the
712 parent of the window for that help was called, is asked for its HelpID.
713 For compatibility reasons this upward search is not implemented for "real" URLs.
714 Help keyword search now is implemented as own method; in former versions it
715 was done via Help::Start, but this implementation conflicted with the upward search.
718 INetURLObject
aParser( rURL
);
719 INetProtocol nProtocol
= aParser
.GetProtocol();
720 String
aHelpModuleName( GetHelpModuleName_Impl() );
722 ::rtl::OUString sKeyword
;
725 case INET_PROT_VND_SUN_STAR_HELP
:
726 // already a vnd.sun.star.help URL -> nothing to do
731 // no URL, just a HelpID (maybe empty in case of keyword search)
732 aHelpURL
= CreateHelpURL_Impl( rURL
, aHelpModuleName
);
734 // pb i91715: strings begin with ".HelpId:" are not words of the basic ide
735 // they are helpid-strings used by the testtool -> so we ignore them
736 static const String
sHelpIdScheme( DEFINE_CONST_OUSTRING(".HelpId:") );
737 if ( rURL
.Search( sHelpIdScheme
) != 0 )
738 sKeyword
= ::rtl::OUString( rURL
);
740 if ( impl_hasHelpInstalled() && pWindow
&& SfxContentHelper::IsHelpErrorDocument( aHelpURL
) )
742 // no help found -> try with parent help id.
743 Window
* pParent
= pWindow
->GetParent();
746 rtl::OString aHelpId
= pParent
->GetHelpId();
747 aHelpURL
= CreateHelpURL( rtl::OStringToOUString(aHelpId
, RTL_TEXTENCODING_UTF8
), aHelpModuleName
);
748 if ( !SfxContentHelper::IsHelpErrorDocument( aHelpURL
) )
752 pParent
= pParent
->GetParent();
754 // create help url of start page ( helpid == 0 -> start page)
755 aHelpURL
= CreateHelpURL( String(), aHelpModuleName
);
763 if ( !impl_hasHelpInstalled() )
765 if ( impl_showOnlineHelp( aHelpURL
) )
769 NoHelpErrorBox
aErrBox( const_cast< Window
* >( pWindow
) );
775 Reference
< XFrame
> xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
776 DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY
);
778 // check if help window is still open
779 // If not, create a new one and return access directly to the internal sub frame showing the help content
780 // search must be done here; search one desktop level could return an arbitraty frame
781 Reference
< XFrame
> xHelp
= xDesktop
->findFrame(
782 ::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP_TASK")),
783 FrameSearchFlag::CHILDREN
);
784 Reference
< XFrame
> xHelpContent
= xDesktop
->findFrame(
785 ::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP")),
786 FrameSearchFlag::CHILDREN
);
788 SfxHelpWindow_Impl
* pHelpWindow
= 0;
790 pHelpWindow
= impl_createHelp(xHelp
, xHelpContent
);
792 pHelpWindow
= (SfxHelpWindow_Impl
*)VCLUnoHelper::GetWindow(xHelp
->getComponentWindow());
793 if (!xHelp
.is() || !xHelpContent
.is() || !pHelpWindow
)
797 rtl::OStringBuffer
aTmp(RTL_CONSTASCII_STRINGPARAM("SfxHelp: HelpId = "));
798 aTmp
.append(rtl::OUStringToOString(aHelpURL
, RTL_TEXTENCODING_UTF8
));
799 OSL_TRACE( aTmp
.getStr() );
802 pHelpWindow
->SetHelpURL( aHelpURL
);
803 pHelpWindow
->loadHelpContent(aHelpURL
);
804 if ( rKeyword
.Len() )
805 pHelpWindow
->OpenKeyword( rKeyword
);
807 Reference
< ::com::sun::star::awt::XTopWindow
> xTopWindow( xHelp
->getContainerWindow(), UNO_QUERY
);
808 if ( xTopWindow
.is() )
809 xTopWindow
->toFront();
814 String
SfxHelp::CreateHelpURL( const String
& aCommandURL
, const String
& rModuleName
)
817 SfxHelp
* pHelp
= (static_cast< SfxHelp
* >(Application::GetHelp()) );
819 aURL
= pHelp
->CreateHelpURL_Impl( aCommandURL
, rModuleName
);
823 void SfxHelp::OpenHelpAgent( SfxFrame
*, const rtl::OString
& sHelpId
)
825 SfxHelp
* pHelp
= (static_cast< SfxHelp
* >(Application::GetHelp()) );
827 pHelp
->OpenHelpAgent( sHelpId
);
830 void SfxHelp::OpenHelpAgent( const rtl::OString
& sHelpId
)
832 if ( SvtHelpOptions().IsHelpAgentAutoStartMode() )
834 SfxHelpOptions_Impl
*pOpt
= pImp
->GetOptions();
835 if ( !pOpt
->HasId( sHelpId
) )
841 aURL
.Complete
= CreateHelpURL_Impl( rtl::OStringToOUString(sHelpId
, RTL_TEXTENCODING_UTF8
), GetHelpModuleName_Impl() );
842 Reference
< XURLTransformer
> xTrans( ::comphelper::getProcessServiceFactory()->createInstance(
843 ::rtl::OUString("com.sun.star.util.URLTransformer") ), UNO_QUERY
);
844 xTrans
->parseStrict(aURL
);
846 Reference
< XFrame
> xCurrentFrame
;
847 Reference
< XDesktop
> xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
848 DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY
);
850 xCurrentFrame
= xDesktop
->getCurrentFrame();
852 Reference
< XDispatchProvider
> xDispProv( xCurrentFrame
, UNO_QUERY
);
853 Reference
< XDispatch
> xHelpDispatch
;
854 if ( xDispProv
.is() )
855 xHelpDispatch
= xDispProv
->queryDispatch(
856 aURL
, ::rtl::OUString("_helpagent"),
857 FrameSearchFlag::PARENT
| FrameSearchFlag::SELF
);
859 DBG_ASSERT( xHelpDispatch
.is(), "OpenHelpAgent: could not get a dispatcher!" );
860 if ( xHelpDispatch
.is() )
861 xHelpDispatch
->dispatch( aURL
, Sequence
< PropertyValue
>() );
863 catch (const Exception
&)
865 SAL_WARN( "sfx2.appl", "OpenHelpAgent: caught an exception while executing the dispatch!" );
870 String
SfxHelp::GetDefaultHelpModule()
872 return getDefaultModule_Impl();
875 ::rtl::OUString
SfxHelp::GetCurrentModuleIdentifier()
877 return getCurrentModuleIdentifier_Impl();
880 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */