merge the formfield patch from ooo-build
[ooovba.git] / sfx2 / source / appl / sfxhelp.cxx
blob6704ab5389ebf00a9c2eca9d2e308005547cd362
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"
36 #include <algorithm>
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>
43 #endif
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"
87 #include "helper.hxx"
88 #include "app.hrc"
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
104 public:
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
132 Any aLocale =
133 ::utl::ConfigManager::GetConfigManager()->GetDirectConfigProperty(
134 ::utl::ConfigManager::LOCALE );
135 bool bOk = (aLocale >>= aLocaleStr);
136 if ( bOk )
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)
149 bOk = false;
150 String sLang(aLocaleStr);
151 xub_StrLen nSepPos = sLang.Search( '-' );
152 if (nSepPos != STRING_NOTFOUND)
154 bOk = true;
155 sLang = sLang.Copy( 0, nSepPos );
156 sHelpPath = sBaseHelpPath + sLang;
157 if (!osl::DirectoryItem::get(sHelpPath, aDirItem) == osl::FileBase::E_None)
158 bOk = false;
162 if (!bOk)
163 aLocaleStr = rtl::OUString( DEFINE_CONST_UNICODE("en") );
165 return aLocaleStr;
168 void AppendConfigToken_Impl( String& rURL, sal_Bool bQuestionMark )
170 ::rtl::OUString aLocaleStr(HelpLocaleString());
172 // query part exists?
173 if ( bQuestionMark )
174 // no, so start with '?'
175 rURL += '?';
176 else
177 // yes, so only append with '&'
178 rURL += '&';
180 // set parameters
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();
198 // <--
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 );
209 bRet = sal_True;
212 else
214 DBG_ERRORFILE( "Property 'AnchorName' is missing" );
217 catch( ::com::sun::star::uno::Exception& )
220 // --> OD 2009-07-01 #159496#
221 // Application::AcquireSolarMutex( nSolarCount );
222 // <--
224 return bRet;
227 // -----------------------------------------------------------------------
229 class SfxHelpOptions_Impl : public utl::ConfigItem
231 private:
232 SvULongsSort* m_pIds;
234 public:
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();
252 int i = 0;
253 for ( ; pNames != pEnd; ++pNames )
254 *pNames = ::rtl::OUString::createFromAscii( aPropNames[i++] );
256 return aNames;
259 // -----------------------------------------------------------------------
261 SfxHelpOptions_Impl::SfxHelpOptions_Impl()
262 : ConfigItem( ::rtl::OUString::createFromAscii("Office.SFX/Help") )
263 , m_pIds( NULL )
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() )
277 switch ( nProp )
279 case STARTERLIST :
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() );
290 else {
291 DBG_ERRORFILE( "Wrong property type!" );
294 break;
297 default:
298 DBG_ERRORFILE( "Wrong property!" );
299 break;
306 SfxHelpOptions_Impl::~SfxHelpOptions_Impl()
308 delete m_pIds;
311 // class SfxHelp_Impl ----------------------------------------------------
313 class SfxHelp_Impl
315 private:
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
319 void Load();
321 public:
322 SfxHelp_Impl( sal_Bool bDebug );
323 ~SfxHelp_Impl();
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 ),
335 m_pOpt ( NULL )
340 SfxHelp_Impl::~SfxHelp_Impl()
342 delete m_pOpt;
345 void SfxHelp_Impl::Load()
347 // fill modules list
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 );
363 // extract the url
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 )
372 // create help url
373 String aHelpURL = SfxHelp::CreateHelpURL( nHelpId, rModule );
374 // added 'active' parameter
375 aHelpURL.Insert( String( DEFINE_CONST_UNICODE("&Active=true") ), aHelpURL.SearchBackward( '#' ) );
376 // load help string
377 return SfxContentHelper::GetActiveHelpString( aHelpURL );
380 String SfxHelp_Impl::GetHelpText( const rtl::OUString& aCommandURL, const String& rModule )
382 // create help url
383 String aHelpURL = SfxHelp::CreateHelpURL( aCommandURL, rModule );
384 // added 'active' parameter
385 aHelpURL.Insert( String( DEFINE_CONST_UNICODE("&Active=true") ), aHelpURL.SearchBackward( '#' ) );
386 // load help string
387 return SfxContentHelper::GetActiveHelpString( aHelpURL );
390 SfxHelpOptions_Impl* SfxHelp_Impl::GetOptions()
392 // create if not exists
393 if ( !m_pOpt )
394 m_pOpt = new SfxHelpOptions_Impl;
395 return m_pOpt;
398 sal_Bool SfxHelp_Impl::HasModule( const ::rtl::OUString& rModule )
400 if ( !m_aModulesList.size() )
401 Load();
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() )
408 Load();
409 return ( m_aModulesList.begin() != m_aModulesList.end() );
412 // class SfxHelp ---------------------------------------------------------
414 SfxHelp::SfxHelp() :
416 bIsDebug( sal_False ),
417 pImp ( NULL )
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( '_' );
434 if ( nSepPos != -1 )
436 aLanguageStr = aLocaleStr.copy( 0, nSepPos );
437 aCountryStr = aLocaleStr.copy( nSepPos+1 );
439 else
441 nSepPos = aLocaleStr.indexOf( '-' );
442 if ( nSepPos != -1 )
444 aLanguageStr = aLocaleStr.copy( 0, nSepPos );
445 aCountryStr = aLocaleStr.copy( nSepPos+1 );
447 else
449 aLanguageStr = aLocaleStr;
454 SfxHelp::~SfxHelp()
456 delete pImp;
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");
479 else
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 );
494 if ( xDesktop.is() )
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?)" );
507 catch ( Exception& )
509 DBG_ERRORFILE( "SfxHelp::getCurrentModuleIdentifier_Impl(): exception of XModuleManager::identify()" );
513 return sIdentifier;
516 String SfxHelp::GetHelpModuleName_Impl()
518 String sModuleName;
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);
531 if ( xCont.is() )
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;
538 break;
542 catch ( Exception& )
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;
574 else
575 aFactoryShortName = sDefaultModule;
577 sModuleName = String( aFactoryShortName );
578 return sModuleName;
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
588 String aHelpURL;
589 if ( aTicket.Len() )
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");
595 if ( !nHelpId )
597 // no help id -> start page
598 aHelpURL += DEFINE_CONST_UNICODE("&HELP_ContextID=start");
600 else
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=");
609 aHelpURL += aUser;
610 aHelpURL += DEFINE_CONST_UNICODE("&HELP_Ticket=");
611 aHelpURL += aTicket;
612 aHelpURL += DEFINE_CONST_UNICODE("&HELP_Language=");
613 aHelpURL += aLanguageStr;
614 if ( aCountryStr.Len() )
616 aHelpURL += DEFINE_CONST_UNICODE("&HELP_Country=");
617 aHelpURL += aCountryStr;
620 else
622 sal_Bool bHasAnchor = sal_False;
623 String aAnchor;
624 aHelpURL = String::CreateFromAscii("vnd.sun.star.help://");
625 aHelpURL += aModuleName;
627 if ( !nHelpId )
628 aHelpURL += String::CreateFromAscii("/start");
629 else
631 aHelpURL += '/';
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 );
641 if ( bHasAnchor )
643 aHelpURL += '#';
644 aHelpURL += aAnchor;
648 return aHelpURL;
651 String SfxHelp::CreateHelpURL_Impl( const String& aCommandURL, const String& rModuleName )
653 // build up the help URL
654 String aHelpURL;
655 sal_Bool bHasAnchor = sal_False;
656 String aAnchor;
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");
677 else
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");
688 else
690 aHelpURL += '/';
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 );
703 if ( bHasAnchor )
705 aHelpURL += '#';
706 aHelpURL += aAnchor;
709 return aHelpURL;
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(
723 OFFICE_HELP_TASK,
724 FrameSearchFlag::TASKS | FrameSearchFlag::CREATE);
725 if (!xHelpTask.is())
726 return 0;
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 >() ))
737 // Customize UI ...
738 xHelpTask->setName( OFFICE_HELP_TASK );
740 Reference< XPropertySet > xProps(xHelpTask, UNO_QUERY);
741 if (xProps.is())
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())
756 delete pHelpWindow;
758 xHelpContent->setName(OFFICE_HELP);
760 rHelpTask = xHelpTask;
761 rHelpContent = xHelpContent;
762 return pHelpWindow;
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 ) );
775 aErrBox.Execute();
776 return FALSE;
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.
796 if( !bAcceptAsURL )
797 bAcceptAsURL = ( rURL.Search( '.' ) != STRING_NOTFOUND );
799 if ( bAcceptAsURL )
801 aHelpURL = CreateHelpURL_Impl( rURL, GetHelpModuleName_Impl( ) );
803 else
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
825 // in both cases)!
827 Reference< XFrame > xHelp = xDesktop->findFrame(
828 OFFICE_HELP_TASK,
829 FrameSearchFlag::CHILDREN);
830 Reference< XFrame > xHelpContent = xDesktop->findFrame(
831 OFFICE_HELP,
832 FrameSearchFlag::CHILDREN);
834 SfxHelpWindow_Impl* pHelpWindow = 0;
835 if (!xHelp.is())
836 pHelpWindow = impl_createHelp(xHelp, xHelpContent);
837 else
838 pHelpWindow = (SfxHelpWindow_Impl*)VCLUnoHelper::GetWindow(xHelp->getComponentWindow());
839 if (!xHelp.is() || !xHelpContent.is() || !pHelpWindow)
840 return FALSE;
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();
851 return TRUE;
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();
862 while ( pParent )
864 nHelpId = pParent->GetSmartUniqueOrHelpId().GetNum();
865 aHelpURL = CreateHelpURL( nHelpId, aHelpModuleName );
867 if ( !SfxContentHelper::IsHelpErrorDocument( aHelpURL ) )
868 break;
869 else
871 pParent = pParent->GetParent();
872 if ( !pParent )
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();
892 while ( pParent )
894 nNewHelpId = pParent->GetHelpId();
895 aHelpText = pImp->GetHelpText( nNewHelpId, aModuleName );
897 if ( aHelpText.Len() > 0 )
898 pParent = NULL;
899 else
900 pParent = pParent->GetParent();
903 if ( bIsDebug && aHelpText.Len() == 0 )
904 nNewHelpId = 0;
907 if ( bIsDebug )
909 aHelpText += DEFINE_CONST_UNICODE("\n\n");
910 aHelpText += aModuleName;
911 aHelpText += DEFINE_CONST_UNICODE(" - ");
912 aHelpText += String::CreateFromInt64( nHelpId );
913 if ( nNewHelpId )
915 aHelpText += DEFINE_CONST_UNICODE(" - ");
916 aHelpText += String::CreateFromInt64( nNewHelpId );
920 return aHelpText;
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?
929 if ( bIsDebug )
931 sHelpText += DEFINE_CONST_UNICODE("\n-------------\n");
932 sHelpText += String( sModuleName );
933 sHelpText += DEFINE_CONST_UNICODE(": ");
934 sHelpText += aCommandURL;
937 return sHelpText;
940 String SfxHelp::CreateHelpURL( ULONG nHelpId, const String& rModuleName )
942 String aURL;
943 SfxHelp* pHelp = SAL_STATIC_CAST( SfxHelp*, Application::GetHelp() );
944 if ( pHelp )
945 aURL = pHelp->CreateHelpURL_Impl( nHelpId, rModuleName );
946 return aURL;
949 String SfxHelp::CreateHelpURL( const String& aCommandURL, const String& rModuleName )
951 String aURL;
952 SfxHelp* pHelp = SAL_STATIC_CAST( SfxHelp*, Application::GetHelp() );
953 if ( pHelp )
954 aURL = pHelp->CreateHelpURL_Impl( aCommandURL, rModuleName );
955 return aURL;
958 void SfxHelp::OpenHelpAgent( SfxFrame *pFrame, ULONG nHelpId )
960 if ( SvtHelpOptions().IsHelpAgentAutoStartMode() )
962 SfxHelp* pHelp = SAL_STATIC_CAST( SfxHelp*, Application::GetHelp() );
963 if ( pHelp )
965 SfxHelpOptions_Impl *pOpt = pHelp->pImp->GetOptions();
966 if ( !pOpt->HasId( nHelpId ) )
967 return;
971 URL aURL;
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();