Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "sfx2/sfxhelp.hxx"
21 :
22 : #include <set>
23 : #include <algorithm>
24 : #include <com/sun/star/uno/Reference.h>
25 : #include <com/sun/star/frame/Desktop.hpp>
26 : #include <com/sun/star/frame/XFrame.hpp>
27 : #include <com/sun/star/frame/XComponentLoader.hpp>
28 : #include <com/sun/star/lang/XComponent.hpp>
29 : #include <comphelper/processfactory.hxx>
30 : #include <com/sun/star/awt/XWindow.hpp>
31 : #include <com/sun/star/awt/XTopWindow.hpp>
32 : #include <com/sun/star/awt/PosSize.hpp>
33 : #include <com/sun/star/frame/XDesktop.hpp>
34 : #include <com/sun/star/util/URLTransformer.hpp>
35 : #include <com/sun/star/util/XURLTransformer.hpp>
36 : #include <com/sun/star/frame/XDispatch.hpp>
37 : #include <com/sun/star/frame/XDispatchProvider.hpp>
38 : #include <com/sun/star/beans/XPropertySet.hpp>
39 : #include <com/sun/star/frame/FrameSearchFlag.hpp>
40 : #include <toolkit/helper/vclunohelper.hxx>
41 : #include <com/sun/star/frame/ModuleManager.hpp>
42 : #include <com/sun/star/system/SystemShellExecute.hpp>
43 : #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
44 : #include <unotools/configmgr.hxx>
45 : #include <unotools/configitem.hxx>
46 : #include <svtools/helpopt.hxx>
47 : #include <unotools/moduleoptions.hxx>
48 : #include <tools/urlobj.hxx>
49 : #include <ucbhelper/content.hxx>
50 : #include <unotools/pathoptions.hxx>
51 : #include <rtl/ustring.hxx>
52 : #include <osl/process.h>
53 : #include <osl/file.hxx>
54 : #include <unotools/bootstrap.hxx>
55 : #include <rtl/uri.hxx>
56 : #include <vcl/msgbox.hxx>
57 : #include <svtools/ehdl.hxx>
58 : #include <svtools/sfxecode.hxx>
59 :
60 : #include "newhelp.hxx"
61 : #include <sfx2/objsh.hxx>
62 : #include <sfx2/docfac.hxx>
63 : #include "sfx2/sfxresid.hxx"
64 : #include "helper.hxx"
65 : #include "app.hrc"
66 : #include <sfx2/sfxuno.hxx>
67 : #include <vcl/svapp.hxx>
68 : #include <sfx2/frame.hxx>
69 : #include <rtl/strbuf.hxx>
70 : #include <rtl/string.hxx>
71 :
72 : using namespace ::com::sun::star::beans;
73 : using namespace ::com::sun::star::frame;
74 : using namespace ::com::sun::star::uno;
75 : using namespace ::com::sun::star::util;
76 : using namespace ::com::sun::star::frame;
77 : using namespace ::com::sun::star::lang;
78 : using namespace ::com::sun::star::system;
79 :
80 0 : class NoHelpErrorBox : public ErrorBox
81 : {
82 : public:
83 : NoHelpErrorBox( Window* _pParent );
84 :
85 : virtual void RequestHelp( const HelpEvent& rHEvt );
86 : };
87 :
88 0 : NoHelpErrorBox::NoHelpErrorBox( Window* _pParent ) :
89 :
90 0 : ErrorBox( _pParent, WB_OK, SfxResId( RID_STR_HLPFILENOTEXIST ).toString() )
91 : {
92 : // Error message: "No help available"
93 0 : }
94 :
95 0 : void NoHelpErrorBox::RequestHelp( const HelpEvent& )
96 : {
97 : // do nothing, because no help available
98 0 : }
99 :
100 : #define STARTERLIST 0
101 :
102 : static bool impl_hasHelpInstalled( const OUString &rLang );
103 :
104 : /// Return the locale we prefer for displaying help
105 19 : static OUString HelpLocaleString()
106 : {
107 19 : static OUString aLocaleStr;
108 19 : if (aLocaleStr.isEmpty())
109 : {
110 19 : const OUString aEnglish( "en" );
111 : // detect installed locale
112 19 : aLocaleStr = utl::ConfigManager::getLocale();
113 19 : bool bOk = !aLocaleStr.isEmpty();
114 19 : if ( !bOk )
115 19 : aLocaleStr = aEnglish;
116 : else
117 : {
118 0 : OUString aBaseInstallPath;
119 0 : utl::Bootstrap::locateBaseInstallation(aBaseInstallPath);
120 : static const char *szHelpPath = "/help/";
121 :
122 : OUString sHelpPath = aBaseInstallPath +
123 0 : OUString::createFromAscii(szHelpPath) + aLocaleStr;
124 0 : osl::DirectoryItem aDirItem;
125 :
126 0 : if (!osl::DirectoryItem::get(sHelpPath, aDirItem) == osl::FileBase::E_None)
127 : {
128 0 : bOk = false;
129 0 : String sLang(aLocaleStr);
130 0 : xub_StrLen nSepPos = sLang.Search( '-' );
131 0 : if (nSepPos != STRING_NOTFOUND)
132 : {
133 0 : bOk = true;
134 0 : sLang = sLang.Copy( 0, nSepPos );
135 : sHelpPath = aBaseInstallPath +
136 0 : OUString::createFromAscii(szHelpPath) + sLang;
137 0 : if (!osl::DirectoryItem::get(sHelpPath, aDirItem) == osl::FileBase::E_None)
138 0 : bOk = false;
139 0 : }
140 0 : }
141 : }
142 : // if not OK, and not even English installed, we use online help, and
143 : // have to preserve the full locale name
144 19 : if ( !bOk && impl_hasHelpInstalled( aEnglish ) )
145 0 : aLocaleStr = aEnglish;
146 : }
147 19 : return aLocaleStr;
148 : }
149 :
150 19 : void AppendConfigToken( OUStringBuffer& rURL, sal_Bool bQuestionMark, const OUString &rLang )
151 : {
152 19 : OUString aLocaleStr( rLang );
153 19 : if ( aLocaleStr.isEmpty() )
154 0 : aLocaleStr = HelpLocaleString();
155 :
156 : // query part exists?
157 19 : if ( bQuestionMark )
158 : // no, so start with '?'
159 19 : rURL.append('?');
160 : else
161 : // yes, so only append with '&'
162 0 : rURL.append('&');
163 :
164 : // set parameters
165 19 : rURL.append("Language=");
166 19 : rURL.append(aLocaleStr);
167 19 : rURL.append("&System=");
168 19 : rURL.append(SvtHelpOptions().GetSystem());
169 19 : rURL.append("&Version=");
170 19 : rURL.append(utl::ConfigManager::getProductVersion());
171 19 : }
172 :
173 0 : sal_Bool GetHelpAnchor_Impl( const OUString& _rURL, OUString& _rAnchor )
174 : {
175 0 : sal_Bool bRet = sal_False;
176 0 : OUString sAnchor;
177 :
178 : try
179 : {
180 : ::ucbhelper::Content aCnt( INetURLObject( _rURL ).GetMainURL( INetURLObject::NO_DECODE ),
181 : Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
182 0 : comphelper::getProcessComponentContext() );
183 0 : if ( ( aCnt.getPropertyValue( OUString("AnchorName") ) >>= sAnchor ) )
184 : {
185 :
186 0 : if ( !sAnchor.isEmpty() )
187 : {
188 0 : _rAnchor = String( sAnchor );
189 0 : bRet = sal_True;
190 : }
191 : }
192 : else
193 : {
194 : SAL_WARN( "sfx2.appl", "Property 'AnchorName' is missing" );
195 0 : }
196 : }
197 0 : catch (const ::com::sun::star::uno::Exception&)
198 : {
199 : }
200 :
201 0 : return bRet;
202 : }
203 :
204 : class SfxHelpOptions_Impl : public utl::ConfigItem
205 : {
206 : private:
207 : std::set < OString > m_aIds;
208 :
209 : public:
210 : SfxHelpOptions_Impl();
211 : ~SfxHelpOptions_Impl();
212 :
213 143 : bool HasId( const OString& rId ) { return m_aIds.size() ? m_aIds.find( rId ) != m_aIds.end() : false; }
214 : virtual void Notify( const com::sun::star::uno::Sequence< OUString >& aPropertyNames );
215 : virtual void Commit();
216 : };
217 :
218 8 : static Sequence< OUString > GetPropertyNames()
219 : {
220 : static const char* aPropNames[] =
221 : {
222 : "HelpAgentStarterList",
223 : };
224 :
225 8 : const int nCount = sizeof( aPropNames ) / sizeof( const char* );
226 8 : Sequence< OUString > aNames( nCount );
227 8 : OUString* pNames = aNames.getArray();
228 8 : OUString* pEnd = pNames + aNames.getLength();
229 8 : int i = 0;
230 16 : for ( ; pNames != pEnd; ++pNames )
231 8 : *pNames = OUString::createFromAscii( aPropNames[i++] );
232 :
233 8 : return aNames;
234 : }
235 :
236 8 : SfxHelpOptions_Impl::SfxHelpOptions_Impl()
237 8 : : ConfigItem( OUString("Office.SFX/Help") )
238 : {
239 8 : Sequence< OUString > aNames = GetPropertyNames();
240 8 : Sequence< Any > aValues = GetProperties( aNames );
241 8 : EnableNotification( aNames );
242 8 : const Any* pValues = aValues.getConstArray();
243 : DBG_ASSERT( aValues.getLength() == aNames.getLength(), "GetProperties failed" );
244 8 : if ( aValues.getLength() == aNames.getLength() )
245 : {
246 16 : for ( int nProp = 0; nProp < aNames.getLength(); nProp++ )
247 : {
248 : DBG_ASSERT( pValues[nProp].hasValue(), "property value missing" );
249 8 : if ( pValues[nProp].hasValue() )
250 : {
251 8 : switch ( nProp )
252 : {
253 : case STARTERLIST :
254 : {
255 8 : OUString aCodedList;
256 8 : if ( pValues[nProp] >>= aCodedList )
257 : {
258 : OString aTmp(
259 : OUStringToOString(
260 8 : aCodedList, RTL_TEXTENCODING_UTF8));
261 8 : sal_Int32 nIndex = 0;
262 592 : do
263 : {
264 592 : OString aToken = aTmp.getToken( 0, ',', nIndex );
265 592 : if ( !aToken.isEmpty() )
266 592 : m_aIds.insert( aToken );
267 : }
268 8 : while ( nIndex >= 0 );
269 : }
270 : else {
271 : SAL_WARN( "sfx2.appl", "Wrong property type!" );
272 : }
273 :
274 8 : break;
275 : }
276 :
277 : default:
278 : SAL_WARN( "sfx2.appl", "Wrong property!" );
279 0 : break;
280 : }
281 : }
282 : }
283 8 : }
284 8 : }
285 :
286 0 : SfxHelpOptions_Impl::~SfxHelpOptions_Impl()
287 : {
288 0 : }
289 :
290 :
291 0 : void SfxHelpOptions_Impl::Notify( const com::sun::star::uno::Sequence< OUString >& )
292 : {
293 0 : }
294 :
295 0 : void SfxHelpOptions_Impl::Commit()
296 : {
297 0 : }
298 :
299 : class SfxHelp_Impl
300 : {
301 : private:
302 : SfxHelpOptions_Impl* m_pOpt; // the options
303 : ::std::vector< OUString > m_aModulesList; // list of all installed modules
304 :
305 : public:
306 : SfxHelp_Impl();
307 : ~SfxHelp_Impl();
308 :
309 : SfxHelpOptions_Impl* GetOptions();
310 : static String GetHelpText( const OUString& aCommandURL, const String& rModule );
311 : };
312 :
313 19 : SfxHelp_Impl::SfxHelp_Impl() :
314 :
315 19 : m_pOpt ( NULL )
316 :
317 : {
318 19 : }
319 :
320 0 : SfxHelp_Impl::~SfxHelp_Impl()
321 : {
322 0 : delete m_pOpt;
323 0 : }
324 :
325 0 : String SfxHelp_Impl::GetHelpText( const OUString& aCommandURL, const String& rModule )
326 : {
327 : // create help url
328 0 : String aHelpURL = SfxHelp::CreateHelpURL( aCommandURL, rModule );
329 : // added 'active' parameter
330 0 : aHelpURL.Insert( String( DEFINE_CONST_UNICODE("&Active=true") ), aHelpURL.SearchBackward( '#' ) );
331 : // load help string
332 0 : return SfxContentHelper::GetActiveHelpString( aHelpURL );
333 : }
334 :
335 143 : SfxHelpOptions_Impl* SfxHelp_Impl::GetOptions()
336 : {
337 : // create if not exists
338 143 : if ( !m_pOpt )
339 8 : m_pOpt = new SfxHelpOptions_Impl;
340 143 : return m_pOpt;
341 : }
342 :
343 19 : SfxHelp::SfxHelp() :
344 :
345 : bIsDebug( sal_False ),
346 19 : pImp ( NULL )
347 :
348 : {
349 : // read the environment variable "HELP_DEBUG"
350 : // if it's set, you will see debug output on active help
351 : {
352 19 : OUString sHelpDebug;
353 19 : OUString sEnvVarName( "HELP_DEBUG" );
354 19 : osl_getEnvironment( sEnvVarName.pData, &sHelpDebug.pData );
355 19 : bIsDebug = !sHelpDebug.isEmpty();
356 : }
357 :
358 19 : pImp = new SfxHelp_Impl();
359 :
360 19 : OUString aLocaleStr = HelpLocaleString();
361 :
362 19 : sal_Int32 nSepPos = aLocaleStr.indexOf( '_' );
363 19 : if ( nSepPos != -1 )
364 : {
365 0 : aLanguageStr = aLocaleStr.copy( 0, nSepPos );
366 0 : aCountryStr = aLocaleStr.copy( nSepPos+1 );
367 : }
368 : else
369 : {
370 19 : nSepPos = aLocaleStr.indexOf( '-' );
371 19 : if ( nSepPos != -1 )
372 : {
373 0 : aLanguageStr = aLocaleStr.copy( 0, nSepPos );
374 0 : aCountryStr = aLocaleStr.copy( nSepPos+1 );
375 : }
376 : else
377 : {
378 19 : aLanguageStr = aLocaleStr;
379 : }
380 19 : }
381 19 : }
382 :
383 0 : SfxHelp::~SfxHelp()
384 : {
385 0 : delete pImp;
386 0 : }
387 :
388 0 : OUString getDefaultModule_Impl()
389 : {
390 0 : OUString sDefaultModule;
391 0 : SvtModuleOptions aModOpt;
392 0 : if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
393 0 : sDefaultModule = DEFINE_CONST_UNICODE("swriter");
394 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
395 0 : sDefaultModule = DEFINE_CONST_UNICODE("scalc");
396 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
397 0 : sDefaultModule = DEFINE_CONST_UNICODE("simpress");
398 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
399 0 : sDefaultModule = DEFINE_CONST_UNICODE("sdraw");
400 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) )
401 0 : sDefaultModule = DEFINE_CONST_UNICODE("smath");
402 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCHART ) )
403 0 : sDefaultModule = DEFINE_CONST_UNICODE("schart");
404 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SBASIC ) )
405 0 : sDefaultModule = DEFINE_CONST_UNICODE("sbasic");
406 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
407 0 : sDefaultModule = DEFINE_CONST_UNICODE("sdatabase");
408 : else
409 : {
410 : SAL_WARN( "sfx2.appl", "getDefaultModule_Impl(): no module installed" );
411 : }
412 0 : return sDefaultModule;
413 : }
414 :
415 0 : OUString getCurrentModuleIdentifier_Impl()
416 : {
417 0 : OUString sIdentifier;
418 0 : Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext();
419 0 : Reference < XModuleManager2 > xModuleManager = ModuleManager::create(xContext);
420 0 : Reference < XDesktop2 > xDesktop = Desktop::create(xContext);
421 0 : Reference < XFrame > xCurrentFrame = xDesktop->getCurrentFrame();
422 :
423 0 : if ( xCurrentFrame.is() )
424 : {
425 : try
426 : {
427 0 : sIdentifier = xModuleManager->identify( xCurrentFrame );
428 : }
429 0 : catch (const ::com::sun::star::frame::UnknownModuleException&)
430 : {
431 : DBG_WARNING( "SfxHelp::getCurrentModuleIdentifier_Impl(): unknown module (help in help?)" );
432 : }
433 0 : catch (const Exception&)
434 : {
435 : SAL_WARN( "sfx2.appl", "SfxHelp::getCurrentModuleIdentifier_Impl(): exception of XModuleManager::identify()" );
436 : }
437 : }
438 :
439 0 : return sIdentifier;
440 : }
441 :
442 0 : OUString SfxHelp::GetHelpModuleName_Impl()
443 : {
444 0 : OUString aFactoryShortName;
445 0 : OUString aModuleIdentifier = getCurrentModuleIdentifier_Impl();
446 :
447 0 : if ( !aModuleIdentifier.isEmpty() )
448 : {
449 : try
450 : {
451 : Reference < XModuleManager2 > xModuleManager(
452 0 : ModuleManager::create(::comphelper::getProcessComponentContext()) );
453 0 : Sequence< PropertyValue > lProps;
454 0 : xModuleManager->getByName( aModuleIdentifier ) >>= lProps;
455 0 : for ( sal_Int32 i = 0; i < lProps.getLength(); ++i )
456 : {
457 0 : if ( lProps[i].Name == "ooSetupFactoryShortName" )
458 : {
459 0 : lProps[i].Value >>= aFactoryShortName;
460 0 : break;
461 : }
462 0 : }
463 : }
464 0 : catch (const Exception&)
465 : {
466 : SAL_WARN( "sfx2.appl", "SfxHelp::GetHelpModuleName_Impl(): exception of XNameAccess::getByName()" );
467 : }
468 : }
469 :
470 0 : OUString sDefaultModule = getDefaultModule_Impl();
471 0 : if ( !aFactoryShortName.isEmpty() )
472 : {
473 : // Map some module identifiers to their "real" help module string.
474 0 : if ( aFactoryShortName == "chart2" )
475 0 : aFactoryShortName = OUString( "schart" );
476 0 : else if ( aFactoryShortName == "BasicIDE" )
477 0 : aFactoryShortName = OUString( "sbasic" );
478 0 : else if ( aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("sweb"))
479 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("sglobal"))
480 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("swxform")) )
481 0 : aFactoryShortName = OUString( "swriter" );
482 0 : else if ( aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbquery"))
483 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbbrowser"))
484 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbrelation"))
485 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbtable"))
486 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbapp"))
487 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbreport"))
488 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("swreport"))
489 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dbbrowser"))
490 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("swform")) )
491 0 : aFactoryShortName = OUString( "sdatabase" );
492 0 : else if ( aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("sbibliography"))
493 0 : || aFactoryShortName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("StartModule")) )
494 0 : aFactoryShortName = sDefaultModule;
495 : }
496 : else
497 0 : aFactoryShortName = sDefaultModule;
498 :
499 0 : return aFactoryShortName;
500 : }
501 :
502 0 : OUString SfxHelp::CreateHelpURL_Impl( const OUString& aCommandURL, const OUString& rModuleName )
503 : {
504 : // build up the help URL
505 0 : OUStringBuffer aHelpURL("vnd.sun.star.help://");
506 0 : sal_Bool bHasAnchor = sal_False;
507 0 : OUString aAnchor;
508 :
509 0 : OUString aModuleName( rModuleName );
510 0 : if (aModuleName.isEmpty())
511 0 : aModuleName = getDefaultModule_Impl();
512 :
513 0 : aHelpURL.append(aModuleName);
514 :
515 0 : if ( aCommandURL.isEmpty() )
516 0 : aHelpURL.append("/start");
517 : else
518 : {
519 0 : aHelpURL.append('/');
520 : aHelpURL.append(rtl::Uri::encode(aCommandURL,
521 : rtl_UriCharClassRelSegment,
522 : rtl_UriEncodeKeepEscapes,
523 0 : RTL_TEXTENCODING_UTF8));
524 :
525 0 : OUStringBuffer aTempURL = aHelpURL;
526 0 : AppendConfigToken( aTempURL, sal_True );
527 0 : bHasAnchor = GetHelpAnchor_Impl(aTempURL.makeStringAndClear(), aAnchor);
528 : }
529 :
530 0 : AppendConfigToken( aHelpURL, sal_True );
531 :
532 0 : if ( bHasAnchor )
533 : {
534 0 : aHelpURL.append('#');
535 0 : aHelpURL.append(aAnchor);
536 : }
537 :
538 0 : return aHelpURL.makeStringAndClear();
539 : }
540 :
541 0 : SfxHelpWindow_Impl* impl_createHelp(Reference< XFrame >& rHelpTask ,
542 : Reference< XFrame >& rHelpContent)
543 : {
544 0 : Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
545 :
546 : // otherwhise - create new help task
547 0 : Reference< XFrame > xHelpTask = xDesktop->findFrame(
548 : OUString("OFFICE_HELP_TASK"),
549 0 : FrameSearchFlag::TASKS | FrameSearchFlag::CREATE);
550 0 : if (!xHelpTask.is())
551 0 : return 0;
552 :
553 : // create all internal windows and sub frames ...
554 0 : Reference< ::com::sun::star::awt::XWindow > xParentWindow = xHelpTask->getContainerWindow();
555 0 : Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow );
556 0 : SfxHelpWindow_Impl* pHelpWindow = new SfxHelpWindow_Impl( xHelpTask, pParentWindow, WB_DOCKBORDER );
557 0 : Reference< ::com::sun::star::awt::XWindow > xHelpWindow = VCLUnoHelper::GetInterface( pHelpWindow );
558 :
559 0 : Reference< XFrame > xHelpContent;
560 0 : if (xHelpTask->setComponent( xHelpWindow, Reference< XController >() ))
561 : {
562 : // Customize UI ...
563 0 : xHelpTask->setName( OUString("OFFICE_HELP_TASK") );
564 :
565 0 : Reference< XPropertySet > xProps(xHelpTask, UNO_QUERY);
566 0 : if (xProps.is())
567 0 : xProps->setPropertyValue(
568 : DEFINE_CONST_UNICODE("Title"),
569 0 : makeAny(SfxResId(STR_HELP_WINDOW_TITLE).toString()));
570 :
571 0 : pHelpWindow->setContainerWindow( xParentWindow );
572 0 : xParentWindow->setVisible(sal_True);
573 0 : xHelpWindow->setVisible(sal_True);
574 :
575 : // This sub frame is created internaly (if we called new SfxHelpWindow_Impl() ...)
576 : // It should exist :-)
577 0 : xHelpContent = xHelpTask->findFrame(OUString("OFFICE_HELP"), FrameSearchFlag::CHILDREN);
578 : }
579 :
580 0 : if (!xHelpContent.is())
581 0 : delete pHelpWindow;
582 :
583 0 : xHelpContent->setName(OUString("OFFICE_HELP"));
584 :
585 0 : rHelpTask = xHelpTask;
586 0 : rHelpContent = xHelpContent;
587 0 : return pHelpWindow;
588 : }
589 :
590 0 : OUString SfxHelp::GetHelpText( const OUString& aCommandURL, const Window* pWindow )
591 : {
592 0 : OUString sModuleName = GetHelpModuleName_Impl();
593 0 : OUString sHelpText = pImp->GetHelpText( aCommandURL, sModuleName );
594 :
595 0 : OString aNewHelpId;
596 :
597 0 : if (pWindow && sHelpText.isEmpty())
598 : {
599 : // no help text found -> try with parent help id.
600 0 : Window* pParent = pWindow->GetParent();
601 0 : while ( pParent )
602 : {
603 0 : aNewHelpId = pParent->GetHelpId();
604 0 : sHelpText = pImp->GetHelpText( OStringToOUString(aNewHelpId, RTL_TEXTENCODING_UTF8), sModuleName );
605 0 : if (!sHelpText.isEmpty())
606 0 : pParent = NULL;
607 : else
608 0 : pParent = pParent->GetParent();
609 : }
610 :
611 0 : if (bIsDebug && sHelpText.isEmpty())
612 0 : aNewHelpId = OString();
613 : }
614 :
615 : // add some debug information?
616 0 : if ( bIsDebug )
617 : {
618 0 : sHelpText += DEFINE_CONST_UNICODE("\n-------------\n");
619 0 : sHelpText += String( sModuleName );
620 0 : sHelpText += DEFINE_CONST_UNICODE(": ");
621 0 : sHelpText += aCommandURL;
622 0 : if ( !aNewHelpId.isEmpty() )
623 : {
624 0 : sHelpText += DEFINE_CONST_UNICODE(" - ");
625 0 : sHelpText += String(OStringToOUString(aNewHelpId, RTL_TEXTENCODING_UTF8));
626 : }
627 : }
628 :
629 0 : return sHelpText;
630 : }
631 :
632 : /// Check for built-in help
633 19 : static bool impl_hasHelpInstalled( const OUString &rLang = OUString() )
634 : {
635 19 : OUStringBuffer aHelpRootURL("vnd.sun.star.help://");
636 19 : AppendConfigToken(aHelpRootURL, sal_True, rLang);
637 19 : Sequence< OUString > aFactories = SfxContentHelper::GetResultSet(aHelpRootURL.makeStringAndClear());
638 :
639 19 : return ( aFactories.getLength() != 0 );
640 : }
641 :
642 0 : sal_Bool SfxHelp::SearchKeyword( const OUString& rKeyword )
643 : {
644 0 : return Start_Impl( String(), NULL, rKeyword );
645 : }
646 :
647 0 : sal_Bool SfxHelp::Start( const OUString& rURL, const Window* pWindow )
648 : {
649 0 : return Start_Impl( rURL, pWindow, OUString() );
650 : }
651 :
652 : /// Redirect the vnd.sun.star.help:// urls to http://help.libreoffice.org
653 0 : static bool impl_showOnlineHelp( const String& rURL )
654 : {
655 0 : String aInternal( "vnd.sun.star.help://" );
656 0 : if ( rURL.Len() <= aInternal.Len() || rURL.Copy( 0, aInternal.Len() ) != aInternal )
657 0 : return false;
658 :
659 0 : OUString aHelpLink( "http://help.libreoffice.org/" );
660 0 : aHelpLink += rURL.Copy( aInternal.Len() );
661 : try
662 : {
663 : Reference< XSystemShellExecute > xSystemShell(
664 0 : SystemShellExecute::create(::comphelper::getProcessComponentContext()) );
665 :
666 0 : xSystemShell->execute( aHelpLink, OUString(), SystemShellExecuteFlags::URIS_ONLY );
667 0 : return true;
668 : }
669 0 : catch (const Exception&)
670 : {
671 : }
672 0 : return false;
673 : }
674 :
675 0 : sal_Bool SfxHelp::Start_Impl(const OUString& rURL, const Window* pWindow, const OUString& rKeyword)
676 : {
677 0 : OUStringBuffer aHelpRootURL("vnd.sun.star.help://");
678 0 : AppendConfigToken(aHelpRootURL, sal_True);
679 0 : Sequence< OUString > aFactories = SfxContentHelper::GetResultSet(aHelpRootURL.makeStringAndClear());
680 :
681 : /* rURL may be
682 : - a "real" URL
683 : - a HelpID (formerly a long, now a string)
684 : If rURL is a URL, CreateHelpURL should be called for this URL
685 : If rURL is an arbitrary string, the same should happen, but the URL should be tried out
686 : if it delivers real help content. In case only the Help Error Document is returned, the
687 : parent of the window for that help was called, is asked for its HelpID.
688 : For compatibility reasons this upward search is not implemented for "real" URLs.
689 : Help keyword search now is implemented as own method; in former versions it
690 : was done via Help::Start, but this implementation conflicted with the upward search.
691 : */
692 0 : String aHelpURL;
693 0 : INetURLObject aParser( rURL );
694 0 : INetProtocol nProtocol = aParser.GetProtocol();
695 0 : String aHelpModuleName( GetHelpModuleName_Impl() );
696 :
697 0 : switch ( nProtocol )
698 : {
699 : case INET_PROT_VND_SUN_STAR_HELP:
700 : // already a vnd.sun.star.help URL -> nothing to do
701 0 : aHelpURL = rURL;
702 0 : break;
703 : default:
704 : {
705 : // no URL, just a HelpID (maybe empty in case of keyword search)
706 0 : aHelpURL = CreateHelpURL_Impl( rURL, aHelpModuleName );
707 :
708 0 : if ( impl_hasHelpInstalled() && pWindow && SfxContentHelper::IsHelpErrorDocument( aHelpURL ) )
709 : {
710 : // no help found -> try with parent help id.
711 0 : Window* pParent = pWindow->GetParent();
712 0 : while ( pParent )
713 : {
714 0 : OString aHelpId = pParent->GetHelpId();
715 0 : aHelpURL = CreateHelpURL( OStringToOUString(aHelpId, RTL_TEXTENCODING_UTF8), aHelpModuleName );
716 0 : if ( !SfxContentHelper::IsHelpErrorDocument( aHelpURL ) )
717 : {
718 : break;
719 : }
720 : else
721 : {
722 0 : pParent = pParent->GetParent();
723 0 : if ( !pParent )
724 : {
725 : // create help url of start page ( helpid == 0 -> start page)
726 0 : aHelpURL = CreateHelpURL( String(), aHelpModuleName );
727 : }
728 : }
729 0 : }
730 : }
731 0 : break;
732 : }
733 : }
734 :
735 0 : if ( !impl_hasHelpInstalled() )
736 : {
737 0 : if ( impl_showOnlineHelp( aHelpURL ) )
738 0 : return sal_True;
739 : else
740 : {
741 0 : NoHelpErrorBox aErrBox( const_cast< Window* >( pWindow ) );
742 0 : aErrBox.Execute();
743 0 : return sal_False;
744 : }
745 : }
746 :
747 0 : Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
748 :
749 : // check if help window is still open
750 : // If not, create a new one and return access directly to the internal sub frame showing the help content
751 : // search must be done here; search one desktop level could return an arbitraty frame
752 0 : Reference< XFrame > xHelp = xDesktop->findFrame(
753 : OUString("OFFICE_HELP_TASK"),
754 0 : FrameSearchFlag::CHILDREN);
755 0 : Reference< XFrame > xHelpContent = xDesktop->findFrame(
756 : OUString("OFFICE_HELP"),
757 0 : FrameSearchFlag::CHILDREN);
758 :
759 0 : SfxHelpWindow_Impl* pHelpWindow = 0;
760 0 : if (!xHelp.is())
761 0 : pHelpWindow = impl_createHelp(xHelp, xHelpContent);
762 : else
763 0 : pHelpWindow = (SfxHelpWindow_Impl*)VCLUnoHelper::GetWindow(xHelp->getComponentWindow());
764 0 : if (!xHelp.is() || !xHelpContent.is() || !pHelpWindow)
765 0 : return sal_False;
766 :
767 : #ifdef DBG_UTIL
768 : OStringBuffer aTmp(RTL_CONSTASCII_STRINGPARAM("SfxHelp: HelpId = "));
769 : aTmp.append(OUStringToOString(aHelpURL, RTL_TEXTENCODING_UTF8));
770 : OSL_TRACE( aTmp.getStr() );
771 : #endif
772 :
773 0 : pHelpWindow->SetHelpURL( aHelpURL );
774 0 : pHelpWindow->loadHelpContent(aHelpURL);
775 0 : if (!rKeyword.isEmpty())
776 0 : pHelpWindow->OpenKeyword( rKeyword );
777 :
778 0 : Reference < ::com::sun::star::awt::XTopWindow > xTopWindow( xHelp->getContainerWindow(), UNO_QUERY );
779 0 : if ( xTopWindow.is() )
780 0 : xTopWindow->toFront();
781 :
782 0 : return sal_True;
783 : }
784 :
785 0 : OUString SfxHelp::CreateHelpURL(const OUString& aCommandURL, const OUString& rModuleName)
786 : {
787 0 : SfxHelp* pHelp = static_cast< SfxHelp* >(Application::GetHelp());
788 0 : return pHelp ? pHelp->CreateHelpURL_Impl( aCommandURL, rModuleName ) : OUString();
789 : }
790 :
791 143 : void SfxHelp::OpenHelpAgent( SfxFrame*, const OString& sHelpId )
792 : {
793 143 : SfxHelp* pHelp = (static_cast< SfxHelp* >(Application::GetHelp()) );
794 143 : if ( pHelp )
795 143 : pHelp->OpenHelpAgent( sHelpId );
796 143 : }
797 :
798 143 : void SfxHelp::OpenHelpAgent( const OString& sHelpId )
799 : {
800 143 : if ( SvtHelpOptions().IsHelpAgentAutoStartMode() )
801 : {
802 143 : SfxHelpOptions_Impl *pOpt = pImp->GetOptions();
803 143 : if ( !pOpt->HasId( sHelpId ) )
804 286 : return;
805 :
806 : try
807 : {
808 0 : URL aURL;
809 0 : aURL.Complete = CreateHelpURL_Impl( OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), GetHelpModuleName_Impl() );
810 0 : Reference< XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
811 0 : xTrans->parseStrict(aURL);
812 :
813 0 : Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
814 0 : Reference < XFrame > xCurrentFrame = xDesktop->getCurrentFrame();
815 :
816 0 : Reference< XDispatchProvider > xDispProv( xCurrentFrame, UNO_QUERY );
817 0 : Reference< XDispatch > xHelpDispatch;
818 0 : if ( xDispProv.is() )
819 0 : xHelpDispatch = xDispProv->queryDispatch(
820 : aURL, OUString("_helpagent"),
821 0 : FrameSearchFlag::PARENT | FrameSearchFlag::SELF );
822 :
823 : DBG_ASSERT( xHelpDispatch.is(), "OpenHelpAgent: could not get a dispatcher!" );
824 0 : if ( xHelpDispatch.is() )
825 0 : xHelpDispatch->dispatch( aURL, Sequence< PropertyValue >() );
826 : }
827 0 : catch (const Exception&)
828 : {
829 : SAL_WARN( "sfx2.appl", "OpenHelpAgent: caught an exception while executing the dispatch!" );
830 : }
831 : }
832 : }
833 :
834 0 : OUString SfxHelp::GetDefaultHelpModule()
835 : {
836 0 : return getDefaultModule_Impl();
837 : }
838 :
839 0 : OUString SfxHelp::GetCurrentModuleIdentifier()
840 : {
841 0 : return getCurrentModuleIdentifier_Impl();
842 : }
843 :
844 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|