| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sfx2.hxx" |
| |
| #include "sfx2/sfxhelp.hxx" |
| |
| #include <set> |
| #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> |
| #include <comphelper/processfactory.hxx> |
| #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 <unotools/moduleoptions.hxx> |
| #include <tools/urlobj.hxx> |
| #include <unotools/configmgr.hxx> |
| #include <ucbhelper/content.hxx> |
| #include <unotools/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 <svl/svstdarr.hxx> |
| |
| #include "newhelp.hxx" |
| #include <sfx2/objsh.hxx> |
| #include <sfx2/docfac.hxx> |
| #include "sfx2/sfxresid.hxx" |
| #include "helper.hxx" |
| #include "app.hrc" |
| #include <sfx2/sfxuno.hxx> |
| #include <vcl/svapp.hxx> |
| #include <sfx2/frame.hxx> |
| #include <rtl/string.hxx> |
| |
| 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 ); |
| aLocale >>= aLocaleStr; |
| bool bOk = aLocaleStr.getLength() != 0; |
| 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; |
| |
| // --> OD 2009-07-01 #159496# |
| // do not release solar mutex due to crash regarding accessibility |
| // sal_uIntPtr 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& ) |
| { |
| } |
| // --> OD 2009-07-01 #159496# |
| // Application::AcquireSolarMutex( nSolarCount ); |
| // <-- |
| |
| return bRet; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| class SfxHelpOptions_Impl : public utl::ConfigItem |
| { |
| private: |
| std::set < rtl::OString > m_aIds; |
| |
| public: |
| SfxHelpOptions_Impl(); |
| ~SfxHelpOptions_Impl(); |
| |
| bool HasId( const rtl::OString& rId ) { return m_aIds.size() ? m_aIds.find( rId ) != m_aIds.end() : false; } |
| virtual void Notify( const com::sun::star::uno::Sequence< rtl::OUString >& aPropertyNames ); |
| virtual void Commit(); |
| }; |
| |
| 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") ) |
| { |
| 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 ) |
| { |
| const rtl::OString aTmp( OUStringToOString( aCodedList, RTL_TEXTENCODING_UTF8 )); |
| sal_Int32 nIndex = 0; |
| do |
| { |
| rtl::OString aToken = aTmp.getToken( 0, ',', nIndex ); |
| if ( aToken.getLength() ) |
| m_aIds.insert( aToken ); |
| } |
| while ( nIndex >= 0 ); |
| } |
| else { |
| DBG_ERRORFILE( "Wrong property type!" ); |
| } |
| |
| break; |
| } |
| |
| default: |
| DBG_ERRORFILE( "Wrong property!" ); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| SfxHelpOptions_Impl::~SfxHelpOptions_Impl() |
| { |
| } |
| |
| |
| void SfxHelpOptions_Impl::Notify( const com::sun::star::uno::Sequence< rtl::OUString >& ) |
| { |
| } |
| |
| void SfxHelpOptions_Impl::Commit() |
| { |
| } |
| |
| // 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(); |
| static 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( 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 --------------------------------------------------------- |
| /* some test code for HID conversion - please don't remove |
| |
| #include <tools/stream.hxx> |
| void TestHids() |
| { |
| static const char* aModules[] = |
| { |
| "swriter", |
| "scalc", |
| "simpress", |
| "sdraw", |
| "sdatabase", |
| "smath", |
| "schart", |
| "sbasic" |
| }; |
| |
| SvFileStream* pOut[] = |
| { |
| 0,0,0,0,0,0,0,0,0 |
| }; |
| |
| String aIn = String::CreateFromAscii("/data/OOo/replacer/hidsin.lst"); |
| String aOut = String::CreateFromAscii("/data/OOo/replacer/"); |
| SvFileStream aInStrm( aIn, STREAM_READ ); |
| ByteString aBuffer; |
| while ( aInStrm.ReadLine( aBuffer ) ) |
| { |
| ByteString aHid = aBuffer.GetToken(0, ' '); |
| ByteString aNr = aBuffer.GetToken(1, ' '); |
| bool bFound=false; |
| for (sal_Int32 n= 0; n<8; n++) |
| { |
| bFound = false; |
| String aHelpURL = SfxHelp::CreateHelpURL( String( aNr, RTL_TEXTENCODING_UTF8 ), String( aModules[n], RTL_TEXTENCODING_UTF8 ) ); |
| if ( !SfxContentHelper::IsHelpErrorDocument( aHelpURL ) ) |
| { |
| if (!pOut[n]) |
| { |
| String aTmp( aOut ); |
| aTmp += String( aModules[n], RTL_TEXTENCODING_UTF8 ); |
| aTmp += String::CreateFromAscii(".lst"); |
| pOut[n] = new SvFileStream( aTmp, STREAM_WRITE | STREAM_TRUNC ); |
| } |
| pOut[n]->WriteLine( aHid ); |
| bFound = true; |
| break; |
| } |
| } |
| |
| if (!bFound) |
| { |
| if (!pOut[8]) |
| { |
| String aTmp( aOut ); |
| aTmp += String( "notfound", RTL_TEXTENCODING_UTF8 ); |
| aTmp += String::CreateFromAscii(".lst"); |
| pOut[8] = new SvFileStream( aTmp, STREAM_WRITE | STREAM_TRUNC ); |
| } |
| pOut[8]->WriteLine( aHid ); |
| } |
| } |
| |
| for (sal_Int32 n= 0; n<9; n++) |
| DELETEZ( pOut[n] ); |
| } |
| |
| void TestHids2() |
| { |
| static const char* aModules[] = |
| { |
| "swriter", |
| "scalc", |
| "simpress", |
| "smath", |
| "sbasic" |
| }; |
| |
| String aOut = String::CreateFromAscii("/data/OOo/replacer/"); |
| aOut += String::CreateFromAscii("lost.lst"); |
| SvFileStream aOutStrm( aOut, STREAM_WRITE | STREAM_TRUNC ); |
| for (sal_Int32 n= 0; n<5; n++) |
| { |
| String aIn = String::CreateFromAscii("/data/OOo/replacer/help/"); |
| aIn += String::CreateFromAscii( aModules[n] ); |
| aIn += String::CreateFromAscii(".lst"); |
| SvFileStream aInStrm( aIn, STREAM_READ ); |
| ByteString aBuffer; |
| while ( aInStrm.ReadLine( aBuffer ) ) |
| { |
| String aHelpURL = SfxHelp::CreateHelpURL( String( aBuffer, RTL_TEXTENCODING_UTF8 ), String( aModules[n], RTL_TEXTENCODING_UTF8 ) ); |
| if ( SfxContentHelper::IsHelpErrorDocument( aHelpURL ) ) |
| aOutStrm.WriteLine( aBuffer ); |
| } |
| } |
| } |
| |
| #include <tools/stream.hxx> |
| void TestHids3() |
| { |
| static const char* aModules[] = |
| { |
| "swriter", |
| "scalc", |
| "simpress", |
| "sdraw", |
| "sdatabase", |
| "smath", |
| "schart", |
| "sbasic" |
| }; |
| |
| SvFileStream* pOut[] = |
| { |
| 0,0,0,0,0,0,0,0,0 |
| }; |
| |
| String aIn = String::CreateFromAscii("/data/OOo/replacer/hidsin.lst"); |
| String aOut = String::CreateFromAscii("/data/OOo/replacer/quickhelp/"); |
| SvFileStream aInStrm( aIn, STREAM_READ ); |
| ByteString aBuffer; |
| while ( aInStrm.ReadLine( aBuffer ) ) |
| { |
| ByteString aHid = aBuffer.GetToken(0, ' '); |
| ByteString aNr = aBuffer.GetToken(1, ' '); |
| bool bFound=false; |
| for (sal_Int32 n= 0; n<8; n++) |
| { |
| bFound = false; |
| String aHelpURL = SfxHelp::CreateHelpURL( String( aNr, RTL_TEXTENCODING_UTF8 ), String( aModules[n], RTL_TEXTENCODING_UTF8 ) ); |
| if ( SfxContentHelper::GetActiveHelpString( aHelpURL ).Len() ) |
| // if ( SfxHelp_Impl::GetHelpText( String( aNr, RTL_TEXTENCODING_UTF8 ), String( aModules[n], RTL_TEXTENCODING_UTF8 ) ).Len() ) |
| { |
| if (!pOut[n]) |
| { |
| String aTmp( aOut ); |
| aTmp += String( aModules[n], RTL_TEXTENCODING_UTF8 ); |
| aTmp += String::CreateFromAscii(".lst"); |
| pOut[n] = new SvFileStream( aTmp, STREAM_WRITE | STREAM_TRUNC ); |
| } |
| pOut[n]->WriteLine( aHid ); |
| bFound = true; |
| break; |
| } |
| } |
| |
| if (!bFound) |
| { |
| if (!pOut[8]) |
| { |
| String aTmp( aOut ); |
| aTmp += String( "notfound", RTL_TEXTENCODING_UTF8 ); |
| aTmp += String::CreateFromAscii(".lst"); |
| pOut[8] = new SvFileStream( aTmp, STREAM_WRITE | STREAM_TRUNC ); |
| } |
| pOut[8]->WriteLine( aHid ); |
| } |
| } |
| |
| for (sal_Int32 n= 0; n<9; n++) |
| DELETEZ( pOut[n] ); |
| } |
| |
| void TestHids4() |
| { |
| static const char* aModules[] = |
| { |
| "swriter", |
| "scalc", |
| "simpress", |
| "smath", |
| "sbasic" |
| }; |
| |
| String aOut = String::CreateFromAscii("/data/OOo/replacer/quickhelp/"); |
| aOut += String::CreateFromAscii("lost.lst"); |
| SvFileStream aOutStrm( aOut, STREAM_WRITE | STREAM_TRUNC ); |
| for (sal_Int32 n= 0; n<5; n++) |
| { |
| String aIn = String::CreateFromAscii("/data/OOo/replacer/quickhelp/"); |
| aIn += String::CreateFromAscii( aModules[n] ); |
| aIn += String::CreateFromAscii(".lst"); |
| SvFileStream aInStrm( aIn, STREAM_READ ); |
| ByteString aBuffer; |
| while ( aInStrm.ReadLine( aBuffer ) ) |
| { |
| String aHelpURL = SfxHelp::CreateHelpURL( String( aBuffer, RTL_TEXTENCODING_UTF8 ), String( aModules[n], RTL_TEXTENCODING_UTF8 ) ); |
| if ( !SfxContentHelper::GetActiveHelpString( aHelpURL ).Len() ) |
| aOutStrm.WriteLine( aBuffer ); |
| } |
| } |
| } |
| */ |
| |
| 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( 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 ) |
| aModuleName = getDefaultModule_Impl(); |
| |
| 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_UTF8 )); |
| |
| 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; |
| } |
| |
| 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( |
| ::rtl::OUString(DEFINE_CONST_UNICODE("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( ::rtl::OUString(DEFINE_CONST_UNICODE("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(::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP")), FrameSearchFlag::CHILDREN); |
| } |
| |
| if (!xHelpContent.is()) |
| delete pHelpWindow; |
| |
| xHelpContent->setName(::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP"))); |
| |
| rHelpTask = xHelpTask; |
| rHelpContent = xHelpContent; |
| return pHelpWindow; |
| } |
| |
| XubString SfxHelp::GetHelpText( const String& aCommandURL, const Window* pWindow ) |
| { |
| String sModuleName = GetHelpModuleName_Impl(); |
| String sHelpText = pImp->GetHelpText( aCommandURL, sModuleName ); |
| |
| ByteString aNewHelpId; |
| |
| if ( pWindow && !sHelpText.Len() ) |
| { |
| // no help text found -> try with parent help id. |
| Window* pParent = pWindow->GetParent(); |
| while ( pParent ) |
| { |
| aNewHelpId = pParent->GetHelpId(); |
| sHelpText = pImp->GetHelpText( String( aNewHelpId, RTL_TEXTENCODING_UTF8 ), sModuleName ); |
| if ( sHelpText.Len() > 0 ) |
| pParent = NULL; |
| else |
| pParent = pParent->GetParent(); |
| } |
| |
| if ( bIsDebug && !sHelpText.Len() ) |
| aNewHelpId.Erase(); |
| } |
| |
| // add some debug information? |
| if ( bIsDebug ) |
| { |
| sHelpText += DEFINE_CONST_UNICODE("\n-------------\n"); |
| sHelpText += String( sModuleName ); |
| sHelpText += DEFINE_CONST_UNICODE(": "); |
| sHelpText += aCommandURL; |
| if ( aNewHelpId.Len() ) |
| { |
| sHelpText += DEFINE_CONST_UNICODE(" - "); |
| sHelpText += String( aNewHelpId, RTL_TEXTENCODING_UTF8 ); |
| } |
| } |
| |
| return sHelpText; |
| } |
| |
| sal_Bool SfxHelp::SearchKeyword( const XubString& rKeyword ) |
| { |
| return Start_Impl( String(), NULL, rKeyword ); |
| } |
| |
| sal_Bool SfxHelp::Start( const String& rURL, const Window* pWindow ) |
| { |
| return Start_Impl( rURL, pWindow, String() ); |
| } |
| |
| sal_Bool SfxHelp::Start_Impl( const String& rURL, const Window* pWindow, const String& rKeyword ) |
| { |
| // 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 sal_False; |
| } |
| |
| /* rURL may be |
| - a "real" URL |
| - a HelpID (formerly a long, now a string) |
| If rURL is a URL, CreateHelpURL should be called for this URL |
| If rURL is an arbitrary string, the same should happen, but the URL should be tried out |
| if it delivers real help content. In case only the Help Error Document is returned, the |
| parent of the window for that help was called, is asked for its HelpID. |
| For compatibility reasons this upward search is not implemented for "real" URLs. |
| Help keyword search now is implemented as own method; in former versions it |
| was done via Help::Start, but this implementation conflicted with the upward search. |
| */ |
| String aHelpURL; |
| INetURLObject aParser( rURL ); |
| INetProtocol nProtocol = aParser.GetProtocol(); |
| String aHelpModuleName( GetHelpModuleName_Impl() ); |
| switch ( nProtocol ) |
| { |
| case INET_PROT_VND_SUN_STAR_HELP: |
| // already a vnd.sun.star.help URL -> nothing to do |
| aHelpURL = rURL; |
| break; |
| default: |
| { |
| // no URL, just a HelpID (maybe empty in case of keyword search) |
| aHelpURL = CreateHelpURL_Impl( rURL, aHelpModuleName ); |
| if ( pWindow && SfxContentHelper::IsHelpErrorDocument( aHelpURL ) ) |
| { |
| // no help found -> try with parent help id. |
| Window* pParent = pWindow->GetParent(); |
| while ( pParent ) |
| { |
| ByteString aHelpId = pParent->GetHelpId(); |
| aHelpURL = CreateHelpURL( String( aHelpId, RTL_TEXTENCODING_UTF8 ), aHelpModuleName ); |
| if ( !SfxContentHelper::IsHelpErrorDocument( aHelpURL ) ) |
| break; |
| else |
| { |
| pParent = pParent->GetParent(); |
| if ( !pParent ) |
| // create help url of start page ( helpid == 0 -> start page) |
| aHelpURL = CreateHelpURL( String(), aHelpModuleName ); |
| } |
| } |
| } |
| break; |
| } |
| } |
| |
| Reference < XFrame > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( |
| DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY ); |
| |
| // check if help window is still open |
| // If not, create a new one and return access directly to the internal sub frame showing the help content |
| // search must be done here; search one desktop level could return an arbitraty frame |
| Reference< XFrame > xHelp = xDesktop->findFrame( |
| ::rtl::OUString(DEFINE_CONST_UNICODE("OFFICE_HELP_TASK")), |
| FrameSearchFlag::CHILDREN); |
| Reference< XFrame > xHelpContent = xDesktop->findFrame( |
| ::rtl::OUString(DEFINE_CONST_UNICODE("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 sal_False; |
| |
| #ifdef DBG_UTIL |
| ByteString aTmp("SfxHelp: HelpId = "); |
| aTmp += ByteString( aHelpURL, RTL_TEXTENCODING_UTF8 ); |
| DBG_TRACE( aTmp.GetBuffer() ); |
| #endif |
| |
| pHelpWindow->SetHelpURL( aHelpURL ); |
| pHelpWindow->loadHelpContent(aHelpURL); |
| if ( rKeyword.Len() ) |
| pHelpWindow->OpenKeyword( rKeyword ); |
| |
| Reference < ::com::sun::star::awt::XTopWindow > xTopWindow( xHelp->getContainerWindow(), UNO_QUERY ); |
| if ( xTopWindow.is() ) |
| xTopWindow->toFront(); |
| |
| return sal_True; |
| } |
| |
| 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*, const rtl::OString& sHelpId ) |
| { |
| SfxHelp* pHelp = SAL_STATIC_CAST( SfxHelp*, Application::GetHelp() ); |
| if ( pHelp ) |
| pHelp->OpenHelpAgent( sHelpId ); |
| } |
| |
| void SfxHelp::OpenHelpAgent( const rtl::OString& sHelpId ) |
| { |
| if ( SvtHelpOptions().IsHelpAgentAutoStartMode() ) |
| { |
| SfxHelpOptions_Impl *pOpt = pImp->GetOptions(); |
| if ( !pOpt->HasId( sHelpId ) ) |
| return; |
| |
| try |
| { |
| URL aURL; |
| aURL.Complete = CreateHelpURL_Impl( String( ByteString(sHelpId), RTL_TEXTENCODING_UTF8 ), GetHelpModuleName_Impl() ); |
| Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( |
| ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" ) ), UNO_QUERY ); |
| xTrans->parseStrict(aURL); |
| |
| Reference < XFrame > xCurrentFrame; |
| Reference < XDesktop > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( |
| DEFINE_CONST_UNICODE("com.sun.star.frame.Desktop") ), UNO_QUERY ); |
| if ( xDesktop.is() ) |
| xCurrentFrame = xDesktop->getCurrentFrame(); |
| |
| Reference< XDispatchProvider > xDispProv( xCurrentFrame, 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(); |
| } |
| |