1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sfxhelp.cxx,v $
10 * $Revision: 1.82.78.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include "sfxhelp.hxx"
37 #include <com/sun/star/uno/Reference.h>
38 #include <com/sun/star/frame/XFrame.hpp>
39 #include <com/sun/star/frame/XComponentLoader.hpp>
40 #include <com/sun/star/lang/XComponent.hpp>
41 #ifndef _UNOTOOLS_PROCESSFACTORY_HXX
42 #include <comphelper/processfactory.hxx>
44 #include <com/sun/star/awt/XWindow.hpp>
45 #include <com/sun/star/awt/XTopWindow.hpp>
46 #include <com/sun/star/awt/PosSize.hpp>
47 #include <com/sun/star/frame/XDesktop.hpp>
48 #include <com/sun/star/util/XURLTransformer.hpp>
49 #include <com/sun/star/frame/XDispatch.hpp>
50 #include <com/sun/star/frame/XDispatchProvider.hpp>
51 #include <com/sun/star/container/XNameAccess.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <com/sun/star/frame/FrameSearchFlag.hpp>
54 #include <toolkit/helper/vclunohelper.hxx>
55 #include <com/sun/star/frame/XModuleManager.hpp>
56 #include <unotools/configmgr.hxx>
57 #include <unotools/configitem.hxx>
58 #include <unotools/localfilehelper.hxx>
59 #include <svtools/helpopt.hxx>
60 #include <svtools/moduleoptions.hxx>
61 #include <tools/urlobj.hxx>
62 #include <ucbhelper/content.hxx>
64 #include <svtools/pathoptions.hxx>
65 #include <rtl/ustring.hxx>
66 #include <osl/process.h>
67 #include <osl/file.hxx>
68 #include <unotools/bootstrap.hxx>
70 #include <rtl/uri.hxx>
71 #include <vcl/msgbox.hxx>
72 #include <svtools/ehdl.hxx>
73 #include <svtools/sfxecode.hxx>
75 #define _SVSTDARR_STRINGSDTOR
76 #define _SVSTDARR_ULONGSSORT
77 #include <svtools/svstdarr.hxx>
79 #include <sfx2/sfxsids.hrc>
80 #include <sfx2/app.hxx>
81 #include <sfx2/viewfrm.hxx>
82 #include <sfx2/msgpool.hxx>
83 #include "newhelp.hxx"
84 #include <sfx2/objsh.hxx>
85 #include <sfx2/docfac.hxx>
86 #include "sfxresid.hxx"
90 using namespace ::com::sun::star::beans
;
91 using namespace ::com::sun::star::frame
;
92 using namespace ::com::sun::star::uno
;
93 using namespace ::com::sun::star::util
;
94 using namespace ::com::sun::star::frame
;
95 using namespace ::com::sun::star::lang
;
97 #define ERROR_TAG String( DEFINE_CONST_UNICODE("Error: ") )
98 #define PATH_TAG String( DEFINE_CONST_UNICODE("\nPath: ") )
100 // class NoHelpErrorBox --------------------------------------------------
102 class NoHelpErrorBox
: public ErrorBox
105 NoHelpErrorBox( Window
* _pParent
);
107 virtual void RequestHelp( const HelpEvent
& rHEvt
);
110 NoHelpErrorBox::NoHelpErrorBox( Window
* _pParent
) :
112 ErrorBox( _pParent
, WB_OK
, String( SfxResId( RID_STR_HLPFILENOTEXIST
) ) )
114 // Error message: "No help available"
117 void NoHelpErrorBox::RequestHelp( const HelpEvent
& )
119 // do nothing, because no help available
122 // -----------------------------------------------------------------------
124 #define STARTERLIST 0
126 rtl::OUString
HelpLocaleString()
128 static rtl::OUString aLocaleStr
;
129 if (!aLocaleStr
.getLength())
131 // detect installed locale
133 ::utl::ConfigManager::GetConfigManager()->GetDirectConfigProperty(
134 ::utl::ConfigManager::LOCALE
);
135 bool bOk
= (aLocale
>>= aLocaleStr
);
138 String sBaseHelpPathString
;
139 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( SvtPathOptions().GetHelpPath(), sBaseHelpPathString
);
141 rtl::OUString
sBaseHelpPath( sBaseHelpPathString
);
142 sBaseHelpPath
+= rtl::OUString::createFromAscii("/");
144 rtl::OUString sHelpPath
= sBaseHelpPath
+ aLocaleStr
;
145 osl::DirectoryItem aDirItem
;
147 if (!osl::DirectoryItem::get(sHelpPath
, aDirItem
) == osl::FileBase::E_None
)
150 String
sLang(aLocaleStr
);
151 xub_StrLen nSepPos
= sLang
.Search( '-' );
152 if (nSepPos
!= STRING_NOTFOUND
)
155 sLang
= sLang
.Copy( 0, nSepPos
);
156 sHelpPath
= sBaseHelpPath
+ sLang
;
157 if (!osl::DirectoryItem::get(sHelpPath
, aDirItem
) == osl::FileBase::E_None
)
163 aLocaleStr
= rtl::OUString( DEFINE_CONST_UNICODE("en") );
168 void AppendConfigToken_Impl( String
& rURL
, sal_Bool bQuestionMark
)
170 ::rtl::OUString
aLocaleStr(HelpLocaleString());
172 // query part exists?
174 // no, so start with '?'
177 // yes, so only append with '&'
181 rURL
+= DEFINE_CONST_UNICODE("Language=");
182 rURL
+= String( aLocaleStr
);
183 rURL
+= DEFINE_CONST_UNICODE("&System=");
184 rURL
+= SvtHelpOptions().GetSystem();
188 // -----------------------------------------------------------------------
190 sal_Bool
GetHelpAnchor_Impl( const String
& _rURL
, String
& _rAnchor
)
192 sal_Bool bRet
= sal_False
;
193 ::rtl::OUString sAnchor
;
195 // --> OD 2009-07-01 #159496#
196 // do not release solar mutex due to crash regarding accessibility
197 // ULONG nSolarCount = Application::ReleaseSolarMutex();
201 ::ucbhelper::Content
aCnt( INetURLObject( _rURL
).GetMainURL( INetURLObject::NO_DECODE
),
202 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> () );
203 if ( ( aCnt
.getPropertyValue( ::rtl::OUString::createFromAscii( "AnchorName" ) ) >>= sAnchor
) )
206 if ( sAnchor
.getLength() > 0 )
208 _rAnchor
= String( sAnchor
);
214 DBG_ERRORFILE( "Property 'AnchorName' is missing" );
217 catch( ::com::sun::star::uno::Exception
& )
220 // --> OD 2009-07-01 #159496#
221 // Application::AcquireSolarMutex( nSolarCount );
227 // -----------------------------------------------------------------------
229 class SfxHelpOptions_Impl
: public utl::ConfigItem
232 SvULongsSort
* m_pIds
;
235 SfxHelpOptions_Impl();
236 ~SfxHelpOptions_Impl();
238 BOOL
HasId( ULONG nId
) { USHORT nDummy
; return m_pIds
? m_pIds
->Seek_Entry( nId
, &nDummy
) : FALSE
; }
241 static Sequence
< ::rtl::OUString
> GetPropertyNames()
243 static const char* aPropNames
[] =
245 "HelpAgentStarterList",
248 const int nCount
= sizeof( aPropNames
) / sizeof( const char* );
249 Sequence
< ::rtl::OUString
> aNames( nCount
);
250 ::rtl::OUString
* pNames
= aNames
.getArray();
251 ::rtl::OUString
* pEnd
= pNames
+ aNames
.getLength();
253 for ( ; pNames
!= pEnd
; ++pNames
)
254 *pNames
= ::rtl::OUString::createFromAscii( aPropNames
[i
++] );
259 // -----------------------------------------------------------------------
261 SfxHelpOptions_Impl::SfxHelpOptions_Impl()
262 : ConfigItem( ::rtl::OUString::createFromAscii("Office.SFX/Help") )
265 Sequence
< ::rtl::OUString
> aNames
= GetPropertyNames();
266 Sequence
< Any
> aValues
= GetProperties( aNames
);
267 EnableNotification( aNames
);
268 const Any
* pValues
= aValues
.getConstArray();
269 DBG_ASSERT( aValues
.getLength() == aNames
.getLength(), "GetProperties failed" );
270 if ( aValues
.getLength() == aNames
.getLength() )
272 for ( int nProp
= 0; nProp
< aNames
.getLength(); nProp
++ )
274 DBG_ASSERT( pValues
[nProp
].hasValue(), "property value missing" );
275 if ( pValues
[nProp
].hasValue() )
281 ::rtl::OUString aCodedList
;
282 if ( pValues
[nProp
] >>= aCodedList
)
284 String
aTmp( aCodedList
);
285 USHORT nCount
= aTmp
.GetTokenCount( ',' );
286 m_pIds
= new SvULongsSort();
287 for ( USHORT n
=0; n
<nCount
; n
++ )
288 m_pIds
->Insert( (ULONG
) aTmp
.GetToken( n
, ',' ).ToInt64() );
291 DBG_ERRORFILE( "Wrong property type!" );
298 DBG_ERRORFILE( "Wrong property!" );
306 SfxHelpOptions_Impl::~SfxHelpOptions_Impl()
311 // class SfxHelp_Impl ----------------------------------------------------
316 sal_Bool m_bIsDebug
; // environment variable "help_debug=1"
317 SfxHelpOptions_Impl
* m_pOpt
; // the options
318 ::std::vector
< ::rtl::OUString
> m_aModulesList
; // list of all installed modules
322 SfxHelp_Impl( sal_Bool bDebug
);
325 SfxHelpOptions_Impl
* GetOptions();
326 String
GetHelpText( ULONG nHelpId
, const String
& rModule
); // get "Active Help"
327 String
GetHelpText( const rtl::OUString
& aCommandURL
, const String
& rModule
);
328 sal_Bool
HasModule( const ::rtl::OUString
& rModule
); // module installed
329 sal_Bool
IsHelpInstalled(); // module list not empty
332 SfxHelp_Impl::SfxHelp_Impl( sal_Bool bDebug
) :
334 m_bIsDebug ( bDebug
),
340 SfxHelp_Impl::~SfxHelp_Impl()
345 void SfxHelp_Impl::Load()
348 // create the help url (empty, without module and helpid)
349 String
sHelpURL( DEFINE_CONST_UNICODE("vnd.sun.star.help://") );
350 AppendConfigToken_Impl( sHelpURL
, sal_True
);
352 // open ucb content and get the list of the help modules
353 // the list contains strings with three tokens "ui title \t type \t url"
354 Sequence
< ::rtl::OUString
> aAllModulesList
= SfxContentHelper::GetResultSet( sHelpURL
);
355 sal_Int32 nLen
= aAllModulesList
.getLength();
356 m_aModulesList
.reserve( nLen
+ 1 );
357 const ::rtl::OUString
* pBegin
= aAllModulesList
.getConstArray();
358 const ::rtl::OUString
* pEnd
= pBegin
+ nLen
;
359 for ( ; pBegin
!= pEnd
; ++pBegin
)
361 // get one module string
362 String
sModule( *pBegin
);
364 String sURL
= sModule
.GetToken( 2, '\t' );
365 // insert the module (the host part of the "vnd.sun.star.help" url)
366 m_aModulesList
.push_back( ::rtl::OUString( INetURLObject( sURL
).GetHost() ) );
370 String
SfxHelp_Impl::GetHelpText( ULONG nHelpId
, const String
& rModule
)
373 String aHelpURL
= SfxHelp::CreateHelpURL( nHelpId
, rModule
);
374 // added 'active' parameter
375 aHelpURL
.Insert( String( DEFINE_CONST_UNICODE("&Active=true") ), aHelpURL
.SearchBackward( '#' ) );
377 return SfxContentHelper::GetActiveHelpString( aHelpURL
);
380 String
SfxHelp_Impl::GetHelpText( const rtl::OUString
& aCommandURL
, const String
& rModule
)
383 String aHelpURL
= SfxHelp::CreateHelpURL( aCommandURL
, rModule
);
384 // added 'active' parameter
385 aHelpURL
.Insert( String( DEFINE_CONST_UNICODE("&Active=true") ), aHelpURL
.SearchBackward( '#' ) );
387 return SfxContentHelper::GetActiveHelpString( aHelpURL
);
390 SfxHelpOptions_Impl
* SfxHelp_Impl::GetOptions()
392 // create if not exists
394 m_pOpt
= new SfxHelpOptions_Impl
;
398 sal_Bool
SfxHelp_Impl::HasModule( const ::rtl::OUString
& rModule
)
400 if ( !m_aModulesList
.size() )
402 return ( ::std::find( m_aModulesList
.begin(), m_aModulesList
.end(), rModule
) != m_aModulesList
.end() );
405 sal_Bool
SfxHelp_Impl::IsHelpInstalled()
407 if ( !m_aModulesList
.size() )
409 return ( m_aModulesList
.begin() != m_aModulesList
.end() );
412 // class SfxHelp ---------------------------------------------------------
416 bIsDebug( sal_False
),
420 // read the environment variable "HELP_DEBUG"
421 // if it's set, you will see debug output on active help
423 ::rtl::OUString sHelpDebug
;
424 ::rtl::OUString
sEnvVarName( RTL_CONSTASCII_USTRINGPARAM( "HELP_DEBUG" ) );
425 osl_getEnvironment( sEnvVarName
.pData
, &sHelpDebug
.pData
);
426 bIsDebug
= ( 0 != sHelpDebug
.getLength() );
429 pImp
= new SfxHelp_Impl( bIsDebug
);
431 ::rtl::OUString aLocaleStr
= HelpLocaleString();
433 sal_Int32 nSepPos
= aLocaleStr
.indexOf( '_' );
436 aLanguageStr
= aLocaleStr
.copy( 0, nSepPos
);
437 aCountryStr
= aLocaleStr
.copy( nSepPos
+1 );
441 nSepPos
= aLocaleStr
.indexOf( '-' );
444 aLanguageStr
= aLocaleStr
.copy( 0, nSepPos
);
445 aCountryStr
= aLocaleStr
.copy( nSepPos
+1 );
449 aLanguageStr
= aLocaleStr
;
459 ::rtl::OUString
getDefaultModule_Impl()
461 rtl::OUString sDefaultModule
;
462 SvtModuleOptions aModOpt
;
463 if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
464 sDefaultModule
= DEFINE_CONST_UNICODE("swriter");
465 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SCALC
) )
466 sDefaultModule
= DEFINE_CONST_UNICODE("scalc");
467 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS
) )
468 sDefaultModule
= DEFINE_CONST_UNICODE("simpress");
469 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SDRAW
) )
470 sDefaultModule
= DEFINE_CONST_UNICODE("sdraw");
471 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SMATH
) )
472 sDefaultModule
= DEFINE_CONST_UNICODE("smath");
473 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SCHART
) )
474 sDefaultModule
= DEFINE_CONST_UNICODE("schart");
475 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SBASIC
) )
476 sDefaultModule
= DEFINE_CONST_UNICODE("sbasic");
477 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SDATABASE
) )
478 sDefaultModule
= DEFINE_CONST_UNICODE("sdatabase");
481 DBG_ERRORFILE( "getDefaultModule_Impl(): no module installed" );
483 return sDefaultModule
;
486 ::rtl::OUString
getCurrentModuleIdentifier_Impl()
488 ::rtl::OUString sIdentifier
;
489 Reference
< XFrame
> xCurrentFrame
;
490 Reference
< XModuleManager
> xModuleManager( ::comphelper::getProcessServiceFactory()->createInstance(
491 DEFINE_CONST_UNICODE("com.sun.star.frame.ModuleManager") ), UNO_QUERY
);
492 Reference
< XDesktop
> xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
493 DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY
);
495 xCurrentFrame
= xDesktop
->getCurrentFrame();
497 if ( xCurrentFrame
.is() && xModuleManager
.is() )
501 sIdentifier
= xModuleManager
->identify( xCurrentFrame
);
503 catch ( ::com::sun::star::frame::UnknownModuleException
& )
505 DBG_WARNING( "SfxHelp::getCurrentModuleIdentifier_Impl(): unknown module (help in help?)" );
509 DBG_ERRORFILE( "SfxHelp::getCurrentModuleIdentifier_Impl(): exception of XModuleManager::identify()" );
516 String
SfxHelp::GetHelpModuleName_Impl()
519 rtl::OUString aFactoryShortName
;
520 rtl::OUString aModuleIdentifier
= getCurrentModuleIdentifier_Impl();
522 if ( aModuleIdentifier
.getLength() > 0 )
526 Reference
< XModuleManager
> xModuleManager(
527 ::comphelper::getProcessServiceFactory()->createInstance(
528 DEFINE_CONST_UNICODE("com.sun.star.frame.ModuleManager") ), UNO_QUERY
);
529 Sequence
< PropertyValue
> lProps
;
530 Reference
< ::com::sun::star::container::XNameAccess
> xCont( xModuleManager
, UNO_QUERY
);
532 xCont
->getByName( aModuleIdentifier
) >>= lProps
;
533 for ( sal_Int32 i
= 0; i
< lProps
.getLength(); ++i
)
535 if ( lProps
[i
].Name
.equalsAscii("ooSetupFactoryShortName") )
537 lProps
[i
].Value
>>= aFactoryShortName
;
544 DBG_ERRORFILE( "SfxHelp::GetHelpModuleName_Impl(): exception of XNameAccess::getByName()" );
548 rtl::OUString sDefaultModule
= getDefaultModule_Impl();
549 if ( aFactoryShortName
.getLength() > 0 )
551 // Map some module identifiers to their "real" help module string.
552 if ( aFactoryShortName
.equalsAscii( "chart2" ) )
553 aFactoryShortName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "schart" ) );
554 else if ( aFactoryShortName
.equalsAscii( "BasicIDE" ) )
555 aFactoryShortName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "sbasic" ) );
556 else if ( aFactoryShortName
.equalsAscii( "sweb" )
557 || aFactoryShortName
.equalsAscii( "sglobal" )
558 || aFactoryShortName
.equalsAscii( "swxform" ) )
559 aFactoryShortName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "swriter" ) );
560 else if ( aFactoryShortName
.equalsAscii( "dbquery" )
561 || aFactoryShortName
.equalsAscii( "dbbrowser" )
562 || aFactoryShortName
.equalsAscii( "dbrelation" )
563 || aFactoryShortName
.equalsAscii( "dbtable" )
564 || aFactoryShortName
.equalsAscii( "dbapp" )
565 || aFactoryShortName
.equalsAscii( "dbreport" )
566 || aFactoryShortName
.equalsAscii( "swreport" )
567 || aFactoryShortName
.equalsAscii( "dbbrowser" )
568 || aFactoryShortName
.equalsAscii( "swform" ) )
569 aFactoryShortName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "sdatabase" ) );
570 else if ( aFactoryShortName
.equalsAscii( "sbibliography" )
571 || aFactoryShortName
.equalsAscii( "StartModule" ) )
572 aFactoryShortName
= sDefaultModule
;
575 aFactoryShortName
= sDefaultModule
;
577 sModuleName
= String( aFactoryShortName
);
581 String
SfxHelp::CreateHelpURL_Impl( ULONG nHelpId
, const String
& rModuleName
)
583 String
aModuleName( rModuleName
);
584 if ( aModuleName
.Len() == 0 )
585 aModuleName
= getDefaultModule_Impl();
587 // build up the help URL
591 // if there is a ticket, we are inside a plugin, so a special Help URL must be sent
592 aHelpURL
= DEFINE_CONST_UNICODE("vnd.sun.star.cmd:help?");
593 aHelpURL
+= DEFINE_CONST_UNICODE("HELP_Request_Mode=contextIndex&HELP_Session_Mode=context&HELP_CallMode=portal&HELP_Device=html");
597 // no help id -> start page
598 aHelpURL
+= DEFINE_CONST_UNICODE("&HELP_ContextID=start");
602 aHelpURL
+= DEFINE_CONST_UNICODE("&HELP_ContextID=");
603 aHelpURL
+= String::CreateFromInt64( nHelpId
);
606 aHelpURL
+= DEFINE_CONST_UNICODE("&HELP_ProgramID=");
607 aHelpURL
+= aModuleName
;
608 aHelpURL
+= DEFINE_CONST_UNICODE("&HELP_User=");
610 aHelpURL
+= DEFINE_CONST_UNICODE("&HELP_Ticket=");
612 aHelpURL
+= DEFINE_CONST_UNICODE("&HELP_Language=");
613 aHelpURL
+= aLanguageStr
;
614 if ( aCountryStr
.Len() )
616 aHelpURL
+= DEFINE_CONST_UNICODE("&HELP_Country=");
617 aHelpURL
+= aCountryStr
;
622 sal_Bool bHasAnchor
= sal_False
;
624 aHelpURL
= String::CreateFromAscii("vnd.sun.star.help://");
625 aHelpURL
+= aModuleName
;
628 aHelpURL
+= String::CreateFromAscii("/start");
632 aHelpURL
+= String::CreateFromInt64( nHelpId
);
634 String aTempURL
= aHelpURL
;
635 AppendConfigToken_Impl( aTempURL
, sal_True
);
636 bHasAnchor
= GetHelpAnchor_Impl( aTempURL
, aAnchor
);
639 AppendConfigToken_Impl( aHelpURL
, sal_True
);
651 String
SfxHelp::CreateHelpURL_Impl( const String
& aCommandURL
, const String
& rModuleName
)
653 // build up the help URL
655 sal_Bool bHasAnchor
= sal_False
;
658 String
aModuleName( rModuleName
);
659 if ( aModuleName
.Len() == 0 )
661 // no active module (quicklaunch?) -> detect default module
662 SvtModuleOptions aModOpt
;
663 if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
664 aModuleName
= DEFINE_CONST_UNICODE("swriter");
665 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SCALC
) )
666 aModuleName
= DEFINE_CONST_UNICODE("scalc");
667 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS
) )
668 aModuleName
= DEFINE_CONST_UNICODE("simpress");
669 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SDRAW
) )
670 aModuleName
= DEFINE_CONST_UNICODE("sdraw");
671 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SMATH
) )
672 aModuleName
= DEFINE_CONST_UNICODE("smath");
673 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SCHART
) )
674 aModuleName
= DEFINE_CONST_UNICODE("schart");
675 else if ( aModOpt
.IsModuleInstalled( SvtModuleOptions::E_SBASIC
) )
676 aModuleName
= DEFINE_CONST_UNICODE("sbasic");
679 DBG_ERRORFILE( "no installed module found" );
683 aHelpURL
= String::CreateFromAscii("vnd.sun.star.help://");
684 aHelpURL
+= aModuleName
;
686 if ( !aCommandURL
.Len() )
687 aHelpURL
+= String::CreateFromAscii("/start");
691 aHelpURL
+= String( rtl::Uri::encode( aCommandURL
,
692 rtl_UriCharClassRelSegment
,
693 rtl_UriEncodeKeepEscapes
,
694 RTL_TEXTENCODING_ASCII_US
));
696 String aTempURL
= aHelpURL
;
697 AppendConfigToken_Impl( aTempURL
, sal_True
);
698 bHasAnchor
= GetHelpAnchor_Impl( aTempURL
, aAnchor
);
701 AppendConfigToken_Impl( aHelpURL
, sal_True
);
712 static ::rtl::OUString OFFICE_HELP_TASK
= ::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP_TASK"));
713 static ::rtl::OUString OFFICE_HELP
= ::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP" ));
715 SfxHelpWindow_Impl
* impl_createHelp(Reference
< XFrame
>& rHelpTask
,
716 Reference
< XFrame
>& rHelpContent
)
718 Reference
< XFrame
> xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
719 DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY
);
721 // otherwhise - create new help task
722 Reference
< XFrame
> xHelpTask
= xDesktop
->findFrame(
724 FrameSearchFlag::TASKS
| FrameSearchFlag::CREATE
);
728 // create all internal windows and sub frames ...
729 Reference
< ::com::sun::star::awt::XWindow
> xParentWindow
= xHelpTask
->getContainerWindow();
730 Window
* pParentWindow
= VCLUnoHelper::GetWindow( xParentWindow
);
731 SfxHelpWindow_Impl
* pHelpWindow
= new SfxHelpWindow_Impl( xHelpTask
, pParentWindow
, WB_DOCKBORDER
);
732 Reference
< ::com::sun::star::awt::XWindow
> xHelpWindow
= VCLUnoHelper::GetInterface( pHelpWindow
);
734 Reference
< XFrame
> xHelpContent
;
735 if (xHelpTask
->setComponent( xHelpWindow
, Reference
< XController
>() ))
738 xHelpTask
->setName( OFFICE_HELP_TASK
);
740 Reference
< XPropertySet
> xProps(xHelpTask
, UNO_QUERY
);
742 xProps
->setPropertyValue(
743 DEFINE_CONST_UNICODE("Title"),
744 makeAny(::rtl::OUString(String(SfxResId(STR_HELP_WINDOW_TITLE
)))));
746 pHelpWindow
->setContainerWindow( xParentWindow
);
747 xParentWindow
->setVisible(sal_True
);
748 xHelpWindow
->setVisible(sal_True
);
750 // This sub frame is created internaly (if we called new SfxHelpWindow_Impl() ...)
751 // It should exist :-)
752 xHelpContent
= xHelpTask
->findFrame(OFFICE_HELP
, FrameSearchFlag::CHILDREN
);
755 if (!xHelpContent
.is())
758 xHelpContent
->setName(OFFICE_HELP
);
760 rHelpTask
= xHelpTask
;
761 rHelpContent
= xHelpContent
;
765 BOOL
SfxHelp::Start( const String
& rURL
, const Window
* pWindow
)
767 // check if help is available
768 String
aHelpRootURL( DEFINE_CONST_OUSTRING("vnd.sun.star.help://") );
769 AppendConfigToken_Impl( aHelpRootURL
, sal_True
);
770 Sequence
< ::rtl::OUString
> aFactories
= SfxContentHelper::GetResultSet( aHelpRootURL
);
771 if ( 0 == aFactories
.getLength() )
773 // no factories -> no help -> error message and return
774 NoHelpErrorBox
aErrBox( const_cast< Window
* >( pWindow
) );
779 // check if it's an URL or a jump mark!
780 String
aHelpURL(rURL
);
781 INetURLObject
aParser (aHelpURL
);
782 ::rtl::OUString sKeyword
;
783 INetProtocol nProtocol
= aParser
.GetProtocol();
784 if ( nProtocol
!= INET_PROT_VND_SUN_STAR_HELP
)
786 // #i90162 Accept anything that is not invalid as help id, as both
787 // uno: URLs used as commands/help ids in the Office and the scheme
788 // used in extension help ids (e.g. com.foocorp.foo-ext:FooDialogButton)
789 // are accepted as INET_PROT_UNO respectively INET_PROT_GENERIC
790 bool bAcceptAsURL
= ( nProtocol
!= INET_PROT_NOT_VALID
);
792 // #i94891 As in some extensions help ids like foo.bar.dummy without
793 // any : have been used that worked before the fix of #i90162 (see
794 // above) strings containing . will be also accepted to avoid brea-
795 // king the help of existing extensions.
797 bAcceptAsURL
= ( rURL
.Search( '.' ) != STRING_NOTFOUND
);
801 aHelpURL
= CreateHelpURL_Impl( rURL
, GetHelpModuleName_Impl( ) );
805 aHelpURL
= CreateHelpURL_Impl( 0, GetHelpModuleName_Impl( ) );
807 // pb i91715: strings begin with ".HelpId:" are not words of the basic ide
808 // they are helpid-strings used by the testtool -> so we ignore them
809 static const String
sHelpIdScheme( DEFINE_CONST_OUSTRING(".HelpId:") );
810 if ( rURL
.Search( sHelpIdScheme
) != 0 )
811 sKeyword
= ::rtl::OUString( rURL
);
815 Reference
< XFrame
> xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(
816 DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY
);
818 // check if help is still open
819 // If not - create new one and return acces directly
820 // to the internal sub frame, which shows the help content.
822 // Note further: We search for this sub frame here directly instead of
823 // the real top level help task ... It's needed to have the same
824 // sub frame available - so we can use it for loading (which is done
827 Reference
< XFrame
> xHelp
= xDesktop
->findFrame(
829 FrameSearchFlag::CHILDREN
);
830 Reference
< XFrame
> xHelpContent
= xDesktop
->findFrame(
832 FrameSearchFlag::CHILDREN
);
834 SfxHelpWindow_Impl
* pHelpWindow
= 0;
836 pHelpWindow
= impl_createHelp(xHelp
, xHelpContent
);
838 pHelpWindow
= (SfxHelpWindow_Impl
*)VCLUnoHelper::GetWindow(xHelp
->getComponentWindow());
839 if (!xHelp
.is() || !xHelpContent
.is() || !pHelpWindow
)
842 pHelpWindow
->SetHelpURL( aHelpURL
);
843 pHelpWindow
->loadHelpContent(aHelpURL
);
844 if ( sKeyword
.getLength() > 0 )
845 pHelpWindow
->OpenKeyword( sKeyword
);
847 Reference
< ::com::sun::star::awt::XTopWindow
> xTopWindow( xHelp
->getContainerWindow(), UNO_QUERY
);
848 if ( xTopWindow
.is() )
849 xTopWindow
->toFront();
854 BOOL
SfxHelp::Start( ULONG nHelpId
, const Window
* pWindow
)
856 String
aHelpModuleName( GetHelpModuleName_Impl() );
857 String aHelpURL
= CreateHelpURL( nHelpId
, aHelpModuleName
);
858 if ( pWindow
&& SfxContentHelper::IsHelpErrorDocument( aHelpURL
) )
860 // no help found -> try with parent help id.
861 Window
* pParent
= pWindow
->GetParent();
864 nHelpId
= pParent
->GetSmartUniqueOrHelpId().GetNum();
865 aHelpURL
= CreateHelpURL( nHelpId
, aHelpModuleName
);
867 if ( !SfxContentHelper::IsHelpErrorDocument( aHelpURL
) )
871 pParent
= pParent
->GetParent();
873 // create help url of start page ( helpid == 0 -> start page)
874 aHelpURL
= CreateHelpURL( 0, aHelpModuleName
);
879 return Start( aHelpURL
, pWindow
);
882 XubString
SfxHelp::GetHelpText( ULONG nHelpId
, const Window
* pWindow
)
884 String aModuleName
= GetHelpModuleName_Impl();
885 String aHelpText
= pImp
->GetHelpText( nHelpId
, aModuleName
);
886 ULONG nNewHelpId
= 0;
888 if ( pWindow
&& aHelpText
.Len() == 0 )
890 // no help text found -> try with parent help id.
891 Window
* pParent
= pWindow
->GetParent();
894 nNewHelpId
= pParent
->GetHelpId();
895 aHelpText
= pImp
->GetHelpText( nNewHelpId
, aModuleName
);
897 if ( aHelpText
.Len() > 0 )
900 pParent
= pParent
->GetParent();
903 if ( bIsDebug
&& aHelpText
.Len() == 0 )
909 aHelpText
+= DEFINE_CONST_UNICODE("\n\n");
910 aHelpText
+= aModuleName
;
911 aHelpText
+= DEFINE_CONST_UNICODE(" - ");
912 aHelpText
+= String::CreateFromInt64( nHelpId
);
915 aHelpText
+= DEFINE_CONST_UNICODE(" - ");
916 aHelpText
+= String::CreateFromInt64( nNewHelpId
);
923 XubString
SfxHelp::GetHelpText( const String
& aCommandURL
, const Window
* )
925 String sModuleName
= GetHelpModuleName_Impl();
926 String sHelpText
= pImp
->GetHelpText( aCommandURL
, sModuleName
);
928 // add some debug information?
931 sHelpText
+= DEFINE_CONST_UNICODE("\n-------------\n");
932 sHelpText
+= String( sModuleName
);
933 sHelpText
+= DEFINE_CONST_UNICODE(": ");
934 sHelpText
+= aCommandURL
;
940 String
SfxHelp::CreateHelpURL( ULONG nHelpId
, const String
& rModuleName
)
943 SfxHelp
* pHelp
= SAL_STATIC_CAST( SfxHelp
*, Application::GetHelp() );
945 aURL
= pHelp
->CreateHelpURL_Impl( nHelpId
, rModuleName
);
949 String
SfxHelp::CreateHelpURL( const String
& aCommandURL
, const String
& rModuleName
)
952 SfxHelp
* pHelp
= SAL_STATIC_CAST( SfxHelp
*, Application::GetHelp() );
954 aURL
= pHelp
->CreateHelpURL_Impl( aCommandURL
, rModuleName
);
958 void SfxHelp::OpenHelpAgent( SfxFrame
*pFrame
, ULONG nHelpId
)
960 if ( SvtHelpOptions().IsHelpAgentAutoStartMode() )
962 SfxHelp
* pHelp
= SAL_STATIC_CAST( SfxHelp
*, Application::GetHelp() );
965 SfxHelpOptions_Impl
*pOpt
= pHelp
->pImp
->GetOptions();
966 if ( !pOpt
->HasId( nHelpId
) )
972 aURL
.Complete
= pHelp
->CreateHelpURL_Impl( nHelpId
, pHelp
->GetHelpModuleName_Impl() );
973 Reference
< XURLTransformer
> xTrans( ::comphelper::getProcessServiceFactory()->createInstance(
974 ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" ) ), UNO_QUERY
);
975 xTrans
->parseStrict(aURL
);
977 Reference
< XDispatchProvider
> xDispProv( pFrame
->GetTopFrame()->GetFrameInterface(), UNO_QUERY
);
978 Reference
< XDispatch
> xHelpDispatch
;
979 if ( xDispProv
.is() )
980 xHelpDispatch
= xDispProv
->queryDispatch(
981 aURL
, ::rtl::OUString::createFromAscii("_helpagent"),
982 FrameSearchFlag::PARENT
| FrameSearchFlag::SELF
);
984 DBG_ASSERT( xHelpDispatch
.is(), "OpenHelpAgent: could not get a dispatcher!" );
985 if ( xHelpDispatch
.is() )
986 xHelpDispatch
->dispatch( aURL
, Sequence
< PropertyValue
>() );
988 catch( const Exception
& )
990 DBG_ERRORFILE( "OpenHelpAgent: caught an exception while executing the dispatch!" );
996 String
SfxHelp::GetDefaultHelpModule()
998 return getDefaultModule_Impl();
1001 ::rtl::OUString
SfxHelp::GetCurrentModuleIdentifier()
1003 return getCurrentModuleIdentifier_Impl();