diff options
Diffstat (limited to 'sfx2/source/appl/sfxhelp.cxx')
-rw-r--r-- | sfx2/source/appl/sfxhelp.cxx | 1001 |
1 files changed, 1001 insertions, 0 deletions
diff --git a/sfx2/source/appl/sfxhelp.cxx b/sfx2/source/appl/sfxhelp.cxx new file mode 100644 index 000000000000..f419bc3e3d55 --- /dev/null +++ b/sfx2/source/appl/sfxhelp.cxx @@ -0,0 +1,1001 @@ + /************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sfxhelp.cxx,v $ + * $Revision: 1.82.78.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include "sfxhelp.hxx" + +#include <algorithm> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <toolkit/helper/vclunohelper.hxx> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <unotools/configmgr.hxx> +#include <unotools/configitem.hxx> +#include <svtools/helpopt.hxx> +#include <svtools/moduleoptions.hxx> +#include <tools/urlobj.hxx> +#include <unotools/configmgr.hxx> +#include <ucbhelper/content.hxx> + +#include <svtools/pathoptions.hxx> +#include <rtl/ustring.hxx> +#include <osl/process.h> +#include <osl/file.hxx> +#include <unotools/bootstrap.hxx> + +#include <rtl/uri.hxx> +#include <vcl/msgbox.hxx> +#include <svtools/ehdl.hxx> +#include <svtools/sfxecode.hxx> + +#define _SVSTDARR_STRINGSDTOR +#define _SVSTDARR_ULONGSSORT +#include <svtools/svstdarr.hxx> + +#include <sfx2/sfxsids.hrc> +#include <sfx2/app.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/msgpool.hxx> +#include "newhelp.hxx" +#include <sfx2/objsh.hxx> +#include <sfx2/docfac.hxx> +#include "sfxresid.hxx" +#include "helper.hxx" +#include "app.hrc" + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; + +#define ERROR_TAG String( DEFINE_CONST_UNICODE("Error: ") ) +#define PATH_TAG String( DEFINE_CONST_UNICODE("\nPath: ") ) + +// class NoHelpErrorBox -------------------------------------------------- + +class NoHelpErrorBox : public ErrorBox +{ +public: + NoHelpErrorBox( Window* _pParent ); + + virtual void RequestHelp( const HelpEvent& rHEvt ); +}; + +NoHelpErrorBox::NoHelpErrorBox( Window* _pParent ) : + + ErrorBox( _pParent, WB_OK, String( SfxResId( RID_STR_HLPFILENOTEXIST ) ) ) +{ + // Error message: "No help available" +} + +void NoHelpErrorBox::RequestHelp( const HelpEvent& ) +{ + // do nothing, because no help available +} + +// ----------------------------------------------------------------------- + +#define STARTERLIST 0 + +rtl::OUString HelpLocaleString() +{ + static rtl::OUString aLocaleStr; + if (!aLocaleStr.getLength()) + { + // detect installed locale + Any aLocale = + ::utl::ConfigManager::GetConfigManager()->GetDirectConfigProperty( + ::utl::ConfigManager::LOCALE ); + bool bOk = (aLocale >>= aLocaleStr); + if ( bOk ) + { + rtl::OUString aBaseInstallPath; + // utl::Bootstrap::PathStatus aBaseLocateResult = + utl::Bootstrap::locateBaseInstallation(aBaseInstallPath); + static const char *szHelpPath = "/help/"; + + rtl::OUString sHelpPath = aBaseInstallPath + + rtl::OUString::createFromAscii(szHelpPath) + aLocaleStr; + osl::DirectoryItem aDirItem; + + if (!osl::DirectoryItem::get(sHelpPath, aDirItem) == osl::FileBase::E_None) + { + bOk = false; + String sLang(aLocaleStr); + xub_StrLen nSepPos = sLang.Search( '-' ); + if (nSepPos != STRING_NOTFOUND) + { + bOk = true; + sLang = sLang.Copy( 0, nSepPos ); + sHelpPath = aBaseInstallPath + + rtl::OUString::createFromAscii(szHelpPath) + sLang; + if (!osl::DirectoryItem::get(sHelpPath, aDirItem) == osl::FileBase::E_None) + bOk = false; + } + } + } + if (!bOk) + aLocaleStr = rtl::OUString( DEFINE_CONST_UNICODE("en") ); + } + return aLocaleStr; +} + +void AppendConfigToken_Impl( String& rURL, sal_Bool bQuestionMark ) +{ + ::rtl::OUString aLocaleStr(HelpLocaleString()); + + // query part exists? + if ( bQuestionMark ) + // no, so start with '?' + rURL += '?'; + else + // yes, so only append with '&' + rURL += '&'; + + // set parameters + rURL += DEFINE_CONST_UNICODE("Language="); + rURL += String( aLocaleStr ); + rURL += DEFINE_CONST_UNICODE("&System="); + rURL += SvtHelpOptions().GetSystem(); + +} + +// ----------------------------------------------------------------------- + +sal_Bool GetHelpAnchor_Impl( const String& _rURL, String& _rAnchor ) +{ + sal_Bool bRet = sal_False; + ::rtl::OUString sAnchor; + + ULONG nSolarCount = Application::ReleaseSolarMutex(); + try + { + ::ucbhelper::Content aCnt( INetURLObject( _rURL ).GetMainURL( INetURLObject::NO_DECODE ), + Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + if ( ( aCnt.getPropertyValue( ::rtl::OUString::createFromAscii( "AnchorName" ) ) >>= sAnchor ) ) + { + + if ( sAnchor.getLength() > 0 ) + { + _rAnchor = String( sAnchor ); + bRet = sal_True; + } + } + else + { + DBG_ERRORFILE( "Property 'AnchorName' is missing" ); + } + } + catch( ::com::sun::star::uno::Exception& ) + { + } + Application::AcquireSolarMutex( nSolarCount ); + + return bRet; +} + +// ----------------------------------------------------------------------- + +class SfxHelpOptions_Impl : public utl::ConfigItem +{ +private: + SvULongsSort* m_pIds; + +public: + SfxHelpOptions_Impl(); + ~SfxHelpOptions_Impl(); + + BOOL HasId( ULONG nId ) { USHORT nDummy; return m_pIds ? m_pIds->Seek_Entry( nId, &nDummy ) : FALSE; } +}; + +static Sequence< ::rtl::OUString > GetPropertyNames() +{ + static const char* aPropNames[] = + { + "HelpAgentStarterList", + }; + + const int nCount = sizeof( aPropNames ) / sizeof( const char* ); + Sequence< ::rtl::OUString > aNames( nCount ); + ::rtl::OUString* pNames = aNames.getArray(); + ::rtl::OUString* pEnd = pNames + aNames.getLength(); + int i = 0; + for ( ; pNames != pEnd; ++pNames ) + *pNames = ::rtl::OUString::createFromAscii( aPropNames[i++] ); + + return aNames; +} + +// ----------------------------------------------------------------------- + +SfxHelpOptions_Impl::SfxHelpOptions_Impl() + : ConfigItem( ::rtl::OUString::createFromAscii("Office.SFX/Help") ) + , m_pIds( NULL ) +{ + Sequence< ::rtl::OUString > aNames = GetPropertyNames(); + Sequence< Any > aValues = GetProperties( aNames ); + EnableNotification( aNames ); + const Any* pValues = aValues.getConstArray(); + DBG_ASSERT( aValues.getLength() == aNames.getLength(), "GetProperties failed" ); + if ( aValues.getLength() == aNames.getLength() ) + { + for ( int nProp = 0; nProp < aNames.getLength(); nProp++ ) + { + DBG_ASSERT( pValues[nProp].hasValue(), "property value missing" ); + if ( pValues[nProp].hasValue() ) + { + switch ( nProp ) + { + case STARTERLIST : + { + ::rtl::OUString aCodedList; + if ( pValues[nProp] >>= aCodedList ) + { + String aTmp( aCodedList ); + USHORT nCount = aTmp.GetTokenCount( ',' ); + m_pIds = new SvULongsSort(); + for ( USHORT n=0; n<nCount; n++ ) + m_pIds->Insert( (ULONG) aTmp.GetToken( n, ',' ).ToInt64() ); + } + else { + DBG_ERRORFILE( "Wrong property type!" ); + } + + break; + } + + default: + DBG_ERRORFILE( "Wrong property!" ); + break; + } + } + } + } +} + +SfxHelpOptions_Impl::~SfxHelpOptions_Impl() +{ + delete m_pIds; +} + +// class SfxHelp_Impl ---------------------------------------------------- + +class SfxHelp_Impl +{ +private: + sal_Bool m_bIsDebug; // environment variable "help_debug=1" + SfxHelpOptions_Impl* m_pOpt; // the options + ::std::vector< ::rtl::OUString > m_aModulesList; // list of all installed modules + void Load(); + +public: + SfxHelp_Impl( sal_Bool bDebug ); + ~SfxHelp_Impl(); + + SfxHelpOptions_Impl* GetOptions(); + String GetHelpText( ULONG nHelpId, const String& rModule ); // get "Active Help" + String GetHelpText( const rtl::OUString& aCommandURL, const String& rModule ); + sal_Bool HasModule( const ::rtl::OUString& rModule ); // module installed + sal_Bool IsHelpInstalled(); // module list not empty +}; + +SfxHelp_Impl::SfxHelp_Impl( sal_Bool bDebug ) : + + m_bIsDebug ( bDebug ), + m_pOpt ( NULL ) + +{ +} + +SfxHelp_Impl::~SfxHelp_Impl() +{ + delete m_pOpt; +} + +void SfxHelp_Impl::Load() +{ + // fill modules list + // create the help url (empty, without module and helpid) + String sHelpURL( DEFINE_CONST_UNICODE("vnd.sun.star.help://") ); + AppendConfigToken_Impl( sHelpURL, sal_True ); + + // open ucb content and get the list of the help modules + // the list contains strings with three tokens "ui title \t type \t url" + Sequence< ::rtl::OUString > aAllModulesList = SfxContentHelper::GetResultSet( sHelpURL ); + sal_Int32 nLen = aAllModulesList.getLength(); + m_aModulesList.reserve( nLen + 1 ); + const ::rtl::OUString* pBegin = aAllModulesList.getConstArray(); + const ::rtl::OUString* pEnd = pBegin + nLen; + for ( ; pBegin != pEnd; ++pBegin ) + { + // get one module string + String sModule( *pBegin ); + // extract the url + String sURL = sModule.GetToken( 2, '\t' ); + // insert the module (the host part of the "vnd.sun.star.help" url) + m_aModulesList.push_back( ::rtl::OUString( INetURLObject( sURL ).GetHost() ) ); + } +} + +String SfxHelp_Impl::GetHelpText( ULONG nHelpId, const String& rModule ) +{ + // create help url + String aHelpURL = SfxHelp::CreateHelpURL( nHelpId, rModule ); + // added 'active' parameter + aHelpURL.Insert( String( DEFINE_CONST_UNICODE("&Active=true") ), aHelpURL.SearchBackward( '#' ) ); + // load help string + return SfxContentHelper::GetActiveHelpString( aHelpURL ); +} + +String SfxHelp_Impl::GetHelpText( const rtl::OUString& aCommandURL, const String& rModule ) +{ + // create help url + String aHelpURL = SfxHelp::CreateHelpURL( aCommandURL, rModule ); + // added 'active' parameter + aHelpURL.Insert( String( DEFINE_CONST_UNICODE("&Active=true") ), aHelpURL.SearchBackward( '#' ) ); + // load help string + return SfxContentHelper::GetActiveHelpString( aHelpURL ); +} + +SfxHelpOptions_Impl* SfxHelp_Impl::GetOptions() +{ + // create if not exists + if ( !m_pOpt ) + m_pOpt = new SfxHelpOptions_Impl; + return m_pOpt; +} + +sal_Bool SfxHelp_Impl::HasModule( const ::rtl::OUString& rModule ) +{ + if ( !m_aModulesList.size() ) + Load(); + return ( ::std::find( m_aModulesList.begin(), m_aModulesList.end(), rModule ) != m_aModulesList.end() ); +} + +sal_Bool SfxHelp_Impl::IsHelpInstalled() +{ + if ( !m_aModulesList.size() ) + Load(); + return ( m_aModulesList.begin() != m_aModulesList.end() ); +} + +// class SfxHelp --------------------------------------------------------- + +SfxHelp::SfxHelp() : + + bIsDebug( sal_False ), + pImp ( NULL ) + +{ + // read the environment variable "HELP_DEBUG" + // if it's set, you will see debug output on active help + { + ::rtl::OUString sHelpDebug; + ::rtl::OUString sEnvVarName( RTL_CONSTASCII_USTRINGPARAM( "HELP_DEBUG" ) ); + osl_getEnvironment( sEnvVarName.pData, &sHelpDebug.pData ); + bIsDebug = ( 0 != sHelpDebug.getLength() ); + } + + pImp = new SfxHelp_Impl( bIsDebug ); + + ::rtl::OUString aLocaleStr = HelpLocaleString(); + + sal_Int32 nSepPos = aLocaleStr.indexOf( '_' ); + if ( nSepPos != -1 ) + { + aLanguageStr = aLocaleStr.copy( 0, nSepPos ); + aCountryStr = aLocaleStr.copy( nSepPos+1 ); + } + else + { + nSepPos = aLocaleStr.indexOf( '-' ); + if ( nSepPos != -1 ) + { + aLanguageStr = aLocaleStr.copy( 0, nSepPos ); + aCountryStr = aLocaleStr.copy( nSepPos+1 ); + } + else + { + aLanguageStr = aLocaleStr; + } + } +} + +SfxHelp::~SfxHelp() +{ + delete pImp; +} + +::rtl::OUString getDefaultModule_Impl() +{ + rtl::OUString sDefaultModule; + SvtModuleOptions aModOpt; + if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + sDefaultModule = DEFINE_CONST_UNICODE("swriter"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + sDefaultModule = DEFINE_CONST_UNICODE("scalc"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + sDefaultModule = DEFINE_CONST_UNICODE("simpress"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + sDefaultModule = DEFINE_CONST_UNICODE("sdraw"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) ) + sDefaultModule = DEFINE_CONST_UNICODE("smath"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCHART ) ) + sDefaultModule = DEFINE_CONST_UNICODE("schart"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SBASIC ) ) + sDefaultModule = DEFINE_CONST_UNICODE("sbasic"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) ) + sDefaultModule = DEFINE_CONST_UNICODE("sdatabase"); + else + { + DBG_ERRORFILE( "getDefaultModule_Impl(): no module installed" ); + } + return sDefaultModule; +} + +::rtl::OUString getCurrentModuleIdentifier_Impl() +{ + ::rtl::OUString sIdentifier; + Reference < XFrame > xCurrentFrame; + Reference < XModuleManager > xModuleManager( ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE("com.sun.star.frame.ModuleManager") ), UNO_QUERY ); + Reference < XDesktop > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY ); + if ( xDesktop.is() ) + xCurrentFrame = xDesktop->getCurrentFrame(); + + if ( xCurrentFrame.is() && xModuleManager.is() ) + { + try + { + sIdentifier = xModuleManager->identify( xCurrentFrame ); + } + catch ( ::com::sun::star::frame::UnknownModuleException& ) + { + DBG_WARNING( "SfxHelp::getCurrentModuleIdentifier_Impl(): unknown module (help in help?)" ); + } + catch ( Exception& ) + { + DBG_ERRORFILE( "SfxHelp::getCurrentModuleIdentifier_Impl(): exception of XModuleManager::identify()" ); + } + } + + return sIdentifier; +} + +String SfxHelp::GetHelpModuleName_Impl() +{ + String sModuleName; + rtl::OUString aFactoryShortName; + rtl::OUString aModuleIdentifier = getCurrentModuleIdentifier_Impl(); + + if ( aModuleIdentifier.getLength() > 0 ) + { + try + { + Reference < XModuleManager > xModuleManager( + ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE("com.sun.star.frame.ModuleManager") ), UNO_QUERY ); + Sequence< PropertyValue > lProps; + Reference< ::com::sun::star::container::XNameAccess > xCont( xModuleManager, UNO_QUERY); + if ( xCont.is() ) + xCont->getByName( aModuleIdentifier ) >>= lProps; + for ( sal_Int32 i = 0; i < lProps.getLength(); ++i ) + { + if ( lProps[i].Name.equalsAscii("ooSetupFactoryShortName") ) + { + lProps[i].Value >>= aFactoryShortName; + break; + } + } + } + catch ( Exception& ) + { + DBG_ERRORFILE( "SfxHelp::GetHelpModuleName_Impl(): exception of XNameAccess::getByName()" ); + } + } + + rtl::OUString sDefaultModule = getDefaultModule_Impl(); + if ( aFactoryShortName.getLength() > 0 ) + { + // Map some module identifiers to their "real" help module string. + if ( aFactoryShortName.equalsAscii( "chart2" ) ) + aFactoryShortName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "schart" ) ); + else if ( aFactoryShortName.equalsAscii( "BasicIDE" ) ) + aFactoryShortName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "sbasic" ) ); + else if ( aFactoryShortName.equalsAscii( "sweb" ) + || aFactoryShortName.equalsAscii( "sglobal" ) + || aFactoryShortName.equalsAscii( "swxform" ) ) + aFactoryShortName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "swriter" ) ); + else if ( aFactoryShortName.equalsAscii( "dbquery" ) + || aFactoryShortName.equalsAscii( "dbbrowser" ) + || aFactoryShortName.equalsAscii( "dbrelation" ) + || aFactoryShortName.equalsAscii( "dbtable" ) + || aFactoryShortName.equalsAscii( "dbapp" ) + || aFactoryShortName.equalsAscii( "dbreport" ) + || aFactoryShortName.equalsAscii( "swreport" ) + || aFactoryShortName.equalsAscii( "dbbrowser" ) + || aFactoryShortName.equalsAscii( "swform" ) ) + aFactoryShortName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "sdatabase" ) ); + else if ( aFactoryShortName.equalsAscii( "sbibliography" ) + || aFactoryShortName.equalsAscii( "StartModule" ) ) + aFactoryShortName = sDefaultModule; + } + else + aFactoryShortName = sDefaultModule; + + sModuleName = String( aFactoryShortName ); + return sModuleName; +} + +String SfxHelp::CreateHelpURL_Impl( ULONG nHelpId, const String& rModuleName ) +{ + String aModuleName( rModuleName ); + if ( aModuleName.Len() == 0 ) + aModuleName = getDefaultModule_Impl(); + + // build up the help URL + String aHelpURL; + if ( aTicket.Len() ) + { + // if there is a ticket, we are inside a plugin, so a special Help URL must be sent + aHelpURL = DEFINE_CONST_UNICODE("vnd.sun.star.cmd:help?"); + aHelpURL += DEFINE_CONST_UNICODE("HELP_Request_Mode=contextIndex&HELP_Session_Mode=context&HELP_CallMode=portal&HELP_Device=html"); + + if ( !nHelpId ) + { + // no help id -> start page + aHelpURL += DEFINE_CONST_UNICODE("&HELP_ContextID=start"); + } + else + { + aHelpURL += DEFINE_CONST_UNICODE("&HELP_ContextID="); + aHelpURL += String::CreateFromInt64( nHelpId ); + } + + aHelpURL += DEFINE_CONST_UNICODE("&HELP_ProgramID="); + aHelpURL += aModuleName; + aHelpURL += DEFINE_CONST_UNICODE("&HELP_User="); + aHelpURL += aUser; + aHelpURL += DEFINE_CONST_UNICODE("&HELP_Ticket="); + aHelpURL += aTicket; + aHelpURL += DEFINE_CONST_UNICODE("&HELP_Language="); + aHelpURL += aLanguageStr; + if ( aCountryStr.Len() ) + { + aHelpURL += DEFINE_CONST_UNICODE("&HELP_Country="); + aHelpURL += aCountryStr; + } + } + else + { + sal_Bool bHasAnchor = sal_False; + String aAnchor; + aHelpURL = String::CreateFromAscii("vnd.sun.star.help://"); + aHelpURL += aModuleName; + + if ( !nHelpId ) + aHelpURL += String::CreateFromAscii("/start"); + else + { + aHelpURL += '/'; + aHelpURL += String::CreateFromInt64( nHelpId ); + + String aTempURL = aHelpURL; + AppendConfigToken_Impl( aTempURL, sal_True ); + bHasAnchor = GetHelpAnchor_Impl( aTempURL, aAnchor ); + } + + AppendConfigToken_Impl( aHelpURL, sal_True ); + + if ( bHasAnchor ) + { + aHelpURL += '#'; + aHelpURL += aAnchor; + } + } + + return aHelpURL; +} + +String SfxHelp::CreateHelpURL_Impl( const String& aCommandURL, const String& rModuleName ) +{ + // build up the help URL + String aHelpURL; + sal_Bool bHasAnchor = sal_False; + String aAnchor; + + String aModuleName( rModuleName ); + if ( aModuleName.Len() == 0 ) + { + // no active module (quicklaunch?) -> detect default module + SvtModuleOptions aModOpt; + if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aModuleName = DEFINE_CONST_UNICODE("swriter"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + aModuleName = DEFINE_CONST_UNICODE("scalc"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + aModuleName = DEFINE_CONST_UNICODE("simpress"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + aModuleName = DEFINE_CONST_UNICODE("sdraw"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) ) + aModuleName = DEFINE_CONST_UNICODE("smath"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCHART ) ) + aModuleName = DEFINE_CONST_UNICODE("schart"); + else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SBASIC ) ) + aModuleName = DEFINE_CONST_UNICODE("sbasic"); + else + { + DBG_ERRORFILE( "no installed module found" ); + } + } + + aHelpURL = String::CreateFromAscii("vnd.sun.star.help://"); + aHelpURL += aModuleName; + + if ( !aCommandURL.Len() ) + aHelpURL += String::CreateFromAscii("/start"); + else + { + aHelpURL += '/'; + aHelpURL += String( rtl::Uri::encode( aCommandURL, + rtl_UriCharClassRelSegment, + rtl_UriEncodeKeepEscapes, + RTL_TEXTENCODING_ASCII_US )); + + String aTempURL = aHelpURL; + AppendConfigToken_Impl( aTempURL, sal_True ); + bHasAnchor = GetHelpAnchor_Impl( aTempURL, aAnchor ); + } + + AppendConfigToken_Impl( aHelpURL, sal_True ); + + if ( bHasAnchor ) + { + aHelpURL += '#'; + aHelpURL += aAnchor; + } + + return aHelpURL; +} + +static ::rtl::OUString OFFICE_HELP_TASK = ::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP_TASK")); +static ::rtl::OUString OFFICE_HELP = ::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP" )); + +SfxHelpWindow_Impl* impl_createHelp(Reference< XFrame >& rHelpTask , + Reference< XFrame >& rHelpContent) +{ + Reference < XFrame > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY ); + + // otherwhise - create new help task + Reference< XFrame > xHelpTask = xDesktop->findFrame( + OFFICE_HELP_TASK, + FrameSearchFlag::TASKS | FrameSearchFlag::CREATE); + if (!xHelpTask.is()) + return 0; + + // create all internal windows and sub frames ... + Reference< ::com::sun::star::awt::XWindow > xParentWindow = xHelpTask->getContainerWindow(); + Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow ); + SfxHelpWindow_Impl* pHelpWindow = new SfxHelpWindow_Impl( xHelpTask, pParentWindow, WB_DOCKBORDER ); + Reference< ::com::sun::star::awt::XWindow > xHelpWindow = VCLUnoHelper::GetInterface( pHelpWindow ); + + Reference< XFrame > xHelpContent; + if (xHelpTask->setComponent( xHelpWindow, Reference< XController >() )) + { + // Customize UI ... + xHelpTask->setName( OFFICE_HELP_TASK ); + + Reference< XPropertySet > xProps(xHelpTask, UNO_QUERY); + if (xProps.is()) + xProps->setPropertyValue( + DEFINE_CONST_UNICODE("Title"), + makeAny(::rtl::OUString(String(SfxResId(STR_HELP_WINDOW_TITLE))))); + + pHelpWindow->setContainerWindow( xParentWindow ); + xParentWindow->setVisible(sal_True); + xHelpWindow->setVisible(sal_True); + + // This sub frame is created internaly (if we called new SfxHelpWindow_Impl() ...) + // It should exist :-) + xHelpContent = xHelpTask->findFrame(OFFICE_HELP, FrameSearchFlag::CHILDREN); + } + + if (!xHelpContent.is()) + delete pHelpWindow; + + xHelpContent->setName(OFFICE_HELP); + + rHelpTask = xHelpTask; + rHelpContent = xHelpContent; + return pHelpWindow; +} + +BOOL SfxHelp::Start( const String& rURL, const Window* pWindow ) +{ + // check if help is available + String aHelpRootURL( DEFINE_CONST_OUSTRING("vnd.sun.star.help://") ); + AppendConfigToken_Impl( aHelpRootURL, sal_True ); + Sequence< ::rtl::OUString > aFactories = SfxContentHelper::GetResultSet( aHelpRootURL ); + if ( 0 == aFactories.getLength() ) + { + // no factories -> no help -> error message and return + NoHelpErrorBox aErrBox( const_cast< Window* >( pWindow ) ); + aErrBox.Execute(); + return FALSE; + } + + // check if it's an URL or a jump mark! + String aHelpURL(rURL ); + INetURLObject aParser (aHelpURL); + ::rtl::OUString sKeyword; + INetProtocol nProtocol = aParser.GetProtocol(); + if ( nProtocol != INET_PROT_VND_SUN_STAR_HELP ) + { + // #i90162 Accept anything that is not invalid as help id, as both + // uno: URLs used as commands/help ids in the Office and the scheme + // used in extension help ids (e.g. com.foocorp.foo-ext:FooDialogButton) + // are accepted as INET_PROT_UNO respectively INET_PROT_GENERIC + bool bAcceptAsURL = ( nProtocol != INET_PROT_NOT_VALID ); + + // #i94891 As in some extensions help ids like foo.bar.dummy without + // any : have been used that worked before the fix of #i90162 (see + // above) strings containing . will be also accepted to avoid brea- + // king the help of existing extensions. + if( !bAcceptAsURL ) + bAcceptAsURL = ( rURL.Search( '.' ) != STRING_NOTFOUND ); + + if ( bAcceptAsURL ) + { + aHelpURL = CreateHelpURL_Impl( rURL, GetHelpModuleName_Impl( ) ); + } + else + { + aHelpURL = CreateHelpURL_Impl( 0, GetHelpModuleName_Impl( ) ); + + // pb i91715: strings begin with ".HelpId:" are not words of the basic ide + // they are helpid-strings used by the testtool -> so we ignore them + static const String sHelpIdScheme( DEFINE_CONST_OUSTRING(".HelpId:") ); + if ( rURL.Search( sHelpIdScheme ) != 0 ) + sKeyword = ::rtl::OUString( rURL ); + } + } + + Reference < XFrame > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY ); + + // check if help is still open + // If not - create new one and return acces directly + // to the internal sub frame, which shows the help content. + + // Note further: We search for this sub frame here directly instead of + // the real top level help task ... It's needed to have the same + // sub frame available - so we can use it for loading (which is done + // in both cases)! + + Reference< XFrame > xHelp = xDesktop->findFrame( + OFFICE_HELP_TASK, + FrameSearchFlag::CHILDREN); + Reference< XFrame > xHelpContent = xDesktop->findFrame( + OFFICE_HELP, + FrameSearchFlag::CHILDREN); + + SfxHelpWindow_Impl* pHelpWindow = 0; + if (!xHelp.is()) + pHelpWindow = impl_createHelp(xHelp, xHelpContent); + else + pHelpWindow = (SfxHelpWindow_Impl*)VCLUnoHelper::GetWindow(xHelp->getComponentWindow()); + if (!xHelp.is() || !xHelpContent.is() || !pHelpWindow) + return FALSE; + + pHelpWindow->SetHelpURL( aHelpURL ); + pHelpWindow->loadHelpContent(aHelpURL); + if ( sKeyword.getLength() > 0 ) + pHelpWindow->OpenKeyword( sKeyword ); + + Reference < ::com::sun::star::awt::XTopWindow > xTopWindow( xHelp->getContainerWindow(), UNO_QUERY ); + if ( xTopWindow.is() ) + xTopWindow->toFront(); + + return TRUE; +} + +BOOL SfxHelp::Start( ULONG nHelpId, const Window* pWindow ) +{ + String aHelpModuleName( GetHelpModuleName_Impl() ); + String aHelpURL = CreateHelpURL( nHelpId, aHelpModuleName ); + if ( pWindow && SfxContentHelper::IsHelpErrorDocument( aHelpURL ) ) + { + // no help found -> try with parent help id. + Window* pParent = pWindow->GetParent(); + while ( pParent ) + { + nHelpId = pParent->GetSmartUniqueOrHelpId().GetNum(); + aHelpURL = CreateHelpURL( nHelpId, aHelpModuleName ); + + if ( !SfxContentHelper::IsHelpErrorDocument( aHelpURL ) ) + break; + else + { + pParent = pParent->GetParent(); + if ( !pParent ) + // create help url of start page ( helpid == 0 -> start page) + aHelpURL = CreateHelpURL( 0, aHelpModuleName ); + } + } + } + + return Start( aHelpURL, pWindow ); +} + +XubString SfxHelp::GetHelpText( ULONG nHelpId, const Window* pWindow ) +{ + String aModuleName = GetHelpModuleName_Impl(); + String aHelpText = pImp->GetHelpText( nHelpId, aModuleName ); + ULONG nNewHelpId = 0; + + if ( pWindow && aHelpText.Len() == 0 ) + { + // no help text found -> try with parent help id. + Window* pParent = pWindow->GetParent(); + while ( pParent ) + { + nNewHelpId = pParent->GetHelpId(); + aHelpText = pImp->GetHelpText( nNewHelpId, aModuleName ); + + if ( aHelpText.Len() > 0 ) + pParent = NULL; + else + pParent = pParent->GetParent(); + } + + if ( bIsDebug && aHelpText.Len() == 0 ) + nNewHelpId = 0; + } + + if ( bIsDebug ) + { + aHelpText += DEFINE_CONST_UNICODE("\n\n"); + aHelpText += aModuleName; + aHelpText += DEFINE_CONST_UNICODE(" - "); + aHelpText += String::CreateFromInt64( nHelpId ); + if ( nNewHelpId ) + { + aHelpText += DEFINE_CONST_UNICODE(" - "); + aHelpText += String::CreateFromInt64( nNewHelpId ); + } + } + + return aHelpText; +} + +XubString SfxHelp::GetHelpText( const String& aCommandURL, const Window* ) +{ + String sModuleName = GetHelpModuleName_Impl(); + String sHelpText = pImp->GetHelpText( aCommandURL, sModuleName ); + + // add some debug information? + if ( bIsDebug ) + { + sHelpText += DEFINE_CONST_UNICODE("\n-------------\n"); + sHelpText += String( sModuleName ); + sHelpText += DEFINE_CONST_UNICODE(": "); + sHelpText += aCommandURL; + } + + return sHelpText; +} + +String SfxHelp::CreateHelpURL( ULONG nHelpId, const String& rModuleName ) +{ + String aURL; + SfxHelp* pHelp = SAL_STATIC_CAST( SfxHelp*, Application::GetHelp() ); + if ( pHelp ) + aURL = pHelp->CreateHelpURL_Impl( nHelpId, rModuleName ); + return aURL; +} + +String SfxHelp::CreateHelpURL( const String& aCommandURL, const String& rModuleName ) +{ + String aURL; + SfxHelp* pHelp = SAL_STATIC_CAST( SfxHelp*, Application::GetHelp() ); + if ( pHelp ) + aURL = pHelp->CreateHelpURL_Impl( aCommandURL, rModuleName ); + return aURL; +} + +void SfxHelp::OpenHelpAgent( SfxFrame *pFrame, ULONG nHelpId ) +{ + if ( SvtHelpOptions().IsHelpAgentAutoStartMode() ) + { + SfxHelp* pHelp = SAL_STATIC_CAST( SfxHelp*, Application::GetHelp() ); + if ( pHelp ) + { + SfxHelpOptions_Impl *pOpt = pHelp->pImp->GetOptions(); + if ( !pOpt->HasId( nHelpId ) ) + return; + + try + { + URL aURL; + aURL.Complete = pHelp->CreateHelpURL_Impl( nHelpId, pHelp->GetHelpModuleName_Impl() ); + Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" ) ), UNO_QUERY ); + xTrans->parseStrict(aURL); + + Reference< XDispatchProvider > xDispProv( pFrame->GetTopFrame()->GetFrameInterface(), UNO_QUERY ); + Reference< XDispatch > xHelpDispatch; + if ( xDispProv.is() ) + xHelpDispatch = xDispProv->queryDispatch( + aURL, ::rtl::OUString::createFromAscii("_helpagent"), + FrameSearchFlag::PARENT | FrameSearchFlag::SELF ); + + DBG_ASSERT( xHelpDispatch.is(), "OpenHelpAgent: could not get a dispatcher!" ); + if ( xHelpDispatch.is() ) + xHelpDispatch->dispatch( aURL, Sequence< PropertyValue >() ); + } + catch( const Exception& ) + { + DBG_ERRORFILE( "OpenHelpAgent: caught an exception while executing the dispatch!" ); + } + } + } +} + +String SfxHelp::GetDefaultHelpModule() +{ + return getDefaultModule_Impl(); +} + +::rtl::OUString SfxHelp::GetCurrentModuleIdentifier() +{ + return getCurrentModuleIdentifier_Impl(); +} + |