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/XFrame2.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::lang;
77 : using namespace ::com::sun::star::system;
78 :
79 0 : class NoHelpErrorBox : public ErrorBox
80 : {
81 : public:
82 : NoHelpErrorBox( Window* _pParent );
83 :
84 : virtual void RequestHelp( const HelpEvent& rHEvt ) SAL_OVERRIDE;
85 : };
86 :
87 0 : NoHelpErrorBox::NoHelpErrorBox( Window* _pParent ) :
88 :
89 0 : ErrorBox( _pParent, WB_OK, SfxResId( RID_STR_HLPFILENOTEXIST ).toString() )
90 : {
91 : // Error message: "No help available"
92 0 : }
93 :
94 0 : void NoHelpErrorBox::RequestHelp( const HelpEvent& )
95 : {
96 : // do nothing, because no help available
97 0 : }
98 :
99 : static bool impl_hasHelpInstalled( const OUString &rLang );
100 :
101 : /// Return the locale we prefer for displaying help
102 0 : static OUString HelpLocaleString()
103 : {
104 0 : static OUString aLocaleStr;
105 0 : if (aLocaleStr.isEmpty())
106 : {
107 0 : const OUString aEnglish( "en" );
108 : // detect installed locale
109 0 : aLocaleStr = utl::ConfigManager::getLocale();
110 0 : bool bOk = !aLocaleStr.isEmpty();
111 0 : if ( !bOk )
112 0 : aLocaleStr = aEnglish;
113 : else
114 : {
115 0 : OUString aBaseInstallPath;
116 0 : utl::Bootstrap::locateBaseInstallation(aBaseInstallPath);
117 : static const char *szHelpPath = "/help/";
118 :
119 0 : OUString sHelpPath = aBaseInstallPath +
120 0 : OUString::createFromAscii(szHelpPath) + aLocaleStr;
121 0 : osl::DirectoryItem aDirItem;
122 :
123 0 : if (osl::DirectoryItem::get(sHelpPath, aDirItem) != osl::FileBase::E_None)
124 : {
125 0 : bOk = false;
126 0 : OUString sLang(aLocaleStr);
127 0 : sal_Int32 nSepPos = sLang.indexOf( '-' );
128 0 : if (nSepPos != -1)
129 : {
130 0 : bOk = true;
131 0 : sLang = sLang.copy( 0, nSepPos );
132 0 : sHelpPath = aBaseInstallPath +
133 0 : OUString::createFromAscii(szHelpPath) + sLang;
134 0 : if (osl::DirectoryItem::get(sHelpPath, aDirItem) != osl::FileBase::E_None)
135 0 : bOk = false;
136 0 : }
137 0 : }
138 : }
139 : // if not OK, and not even English installed, we use online help, and
140 : // have to preserve the full locale name
141 0 : if ( !bOk && impl_hasHelpInstalled( aEnglish ) )
142 0 : aLocaleStr = aEnglish;
143 : }
144 0 : return aLocaleStr;
145 : }
146 :
147 0 : void AppendConfigToken( OUStringBuffer& rURL, bool bQuestionMark, const OUString &rLang )
148 : {
149 0 : OUString aLocaleStr( rLang );
150 0 : if ( aLocaleStr.isEmpty() )
151 0 : aLocaleStr = HelpLocaleString();
152 :
153 : // query part exists?
154 0 : if ( bQuestionMark )
155 : // no, so start with '?'
156 0 : rURL.append('?');
157 : else
158 : // yes, so only append with '&'
159 0 : rURL.append('&');
160 :
161 : // set parameters
162 0 : rURL.append("Language=");
163 0 : rURL.append(aLocaleStr);
164 0 : rURL.append("&System=");
165 0 : rURL.append(SvtHelpOptions().GetSystem());
166 0 : rURL.append("&Version=");
167 0 : rURL.append(utl::ConfigManager::getProductVersion());
168 0 : }
169 :
170 0 : bool GetHelpAnchor_Impl( const OUString& _rURL, OUString& _rAnchor )
171 : {
172 0 : bool bRet = false;
173 0 : OUString sAnchor;
174 :
175 : try
176 : {
177 : ::ucbhelper::Content aCnt( INetURLObject( _rURL ).GetMainURL( INetURLObject::NO_DECODE ),
178 : Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
179 0 : comphelper::getProcessComponentContext() );
180 0 : if ( ( aCnt.getPropertyValue("AnchorName") >>= sAnchor ) )
181 : {
182 :
183 0 : if ( !sAnchor.isEmpty() )
184 : {
185 0 : _rAnchor = sAnchor;
186 0 : bRet = true;
187 : }
188 : }
189 : else
190 : {
191 : SAL_WARN( "sfx.appl", "Property 'AnchorName' is missing" );
192 0 : }
193 : }
194 0 : catch (const ::com::sun::star::uno::Exception&)
195 : {
196 : }
197 :
198 0 : return bRet;
199 : }
200 :
201 : class SfxHelp_Impl
202 : {
203 : public:
204 : static OUString GetHelpText( const OUString& aCommandURL, const OUString& rModule );
205 : };
206 :
207 0 : OUString SfxHelp_Impl::GetHelpText( const OUString& aCommandURL, const OUString& rModule )
208 : {
209 : // create help url
210 0 : OUStringBuffer aHelpURL( SfxHelp::CreateHelpURL( aCommandURL, rModule ) );
211 : // added 'active' parameter
212 0 : sal_Int32 nIndex = aHelpURL.lastIndexOf( '#' );
213 0 : if ( nIndex < 0 )
214 0 : nIndex = aHelpURL.getLength();
215 0 : aHelpURL.insert( nIndex, "&Active=true" );
216 : // load help string
217 0 : return SfxContentHelper::GetActiveHelpString( aHelpURL.makeStringAndClear() );
218 : }
219 :
220 0 : SfxHelp::SfxHelp() :
221 : bIsDebug( false ),
222 0 : pImp ( NULL )
223 : {
224 : // read the environment variable "HELP_DEBUG"
225 : // if it's set, you will see debug output on active help
226 : {
227 0 : OUString sHelpDebug;
228 0 : OUString sEnvVarName( "HELP_DEBUG" );
229 0 : osl_getEnvironment( sEnvVarName.pData, &sHelpDebug.pData );
230 0 : bIsDebug = !sHelpDebug.isEmpty();
231 : }
232 :
233 0 : pImp = new SfxHelp_Impl();
234 0 : }
235 :
236 0 : SfxHelp::~SfxHelp()
237 : {
238 0 : delete pImp;
239 0 : }
240 :
241 0 : OUString getDefaultModule_Impl()
242 : {
243 0 : OUString sDefaultModule;
244 0 : SvtModuleOptions aModOpt;
245 0 : if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
246 0 : sDefaultModule = "swriter";
247 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
248 0 : sDefaultModule = "scalc";
249 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
250 0 : sDefaultModule = "simpress";
251 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
252 0 : sDefaultModule = "sdraw";
253 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) )
254 0 : sDefaultModule = "smath";
255 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SCHART ) )
256 0 : sDefaultModule = "schart";
257 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SBASIC ) )
258 0 : sDefaultModule = "sbasic";
259 0 : else if ( aModOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
260 0 : sDefaultModule = "sdatabase";
261 : else
262 : {
263 : SAL_WARN( "sfx.appl", "getDefaultModule_Impl(): no module installed" );
264 : }
265 0 : return sDefaultModule;
266 : }
267 :
268 0 : OUString getCurrentModuleIdentifier_Impl()
269 : {
270 0 : OUString sIdentifier;
271 0 : Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext();
272 0 : Reference < XModuleManager2 > xModuleManager = ModuleManager::create(xContext);
273 0 : Reference < XDesktop2 > xDesktop = Desktop::create(xContext);
274 0 : Reference < XFrame > xCurrentFrame = xDesktop->getCurrentFrame();
275 :
276 0 : if ( xCurrentFrame.is() )
277 : {
278 : try
279 : {
280 0 : sIdentifier = xModuleManager->identify( xCurrentFrame );
281 : }
282 0 : catch (const ::com::sun::star::frame::UnknownModuleException&)
283 : {
284 : DBG_WARNING( "SfxHelp::getCurrentModuleIdentifier_Impl(): unknown module (help in help?)" );
285 : }
286 0 : catch (const Exception&)
287 : {
288 : SAL_WARN( "sfx.appl", "SfxHelp::getCurrentModuleIdentifier_Impl(): exception of XModuleManager::identify()" );
289 : }
290 : }
291 :
292 0 : return sIdentifier;
293 : }
294 :
295 0 : OUString SfxHelp::GetHelpModuleName_Impl()
296 : {
297 0 : OUString aFactoryShortName;
298 0 : OUString aModuleIdentifier = getCurrentModuleIdentifier_Impl();
299 :
300 0 : if ( !aModuleIdentifier.isEmpty() )
301 : {
302 : try
303 : {
304 : Reference < XModuleManager2 > xModuleManager(
305 0 : ModuleManager::create(::comphelper::getProcessComponentContext()) );
306 0 : Sequence< PropertyValue > lProps;
307 0 : xModuleManager->getByName( aModuleIdentifier ) >>= lProps;
308 0 : for ( sal_Int32 i = 0; i < lProps.getLength(); ++i )
309 : {
310 0 : if ( lProps[i].Name == "ooSetupFactoryShortName" )
311 : {
312 0 : lProps[i].Value >>= aFactoryShortName;
313 0 : break;
314 : }
315 0 : }
316 : }
317 0 : catch (const Exception&)
318 : {
319 : SAL_WARN( "sfx.appl", "SfxHelp::GetHelpModuleName_Impl(): exception of XNameAccess::getByName()" );
320 : }
321 : }
322 :
323 0 : OUString sDefaultModule = getDefaultModule_Impl();
324 0 : if ( !aFactoryShortName.isEmpty() )
325 : {
326 : // Map some module identifiers to their "real" help module string.
327 0 : if ( aFactoryShortName == "chart2" )
328 0 : aFactoryShortName = "schart" ;
329 0 : else if ( aFactoryShortName == "BasicIDE" )
330 0 : aFactoryShortName = "sbasic";
331 0 : else if ( aFactoryShortName == "sweb"
332 0 : || aFactoryShortName == "sglobal"
333 0 : || aFactoryShortName == "swxform" )
334 0 : aFactoryShortName = "swriter" ;
335 0 : else if ( aFactoryShortName == "dbquery"
336 0 : || aFactoryShortName == "dbbrowser"
337 0 : || aFactoryShortName == "dbrelation"
338 0 : || aFactoryShortName == "dbtable"
339 0 : || aFactoryShortName == "dbapp"
340 0 : || aFactoryShortName == "dbreport"
341 0 : || aFactoryShortName == "swreport"
342 0 : || aFactoryShortName == "swform" )
343 0 : aFactoryShortName = "sdatabase";
344 0 : else if ( aFactoryShortName == "sbibliography"
345 0 : || aFactoryShortName == "StartModule" )
346 0 : aFactoryShortName = sDefaultModule;
347 : }
348 : else
349 0 : aFactoryShortName = sDefaultModule;
350 :
351 0 : return aFactoryShortName;
352 : }
353 :
354 0 : OUString SfxHelp::CreateHelpURL_Impl( const OUString& aCommandURL, const OUString& rModuleName )
355 : {
356 : // build up the help URL
357 0 : OUStringBuffer aHelpURL("vnd.sun.star.help://");
358 0 : bool bHasAnchor = false;
359 0 : OUString aAnchor;
360 :
361 0 : OUString aModuleName( rModuleName );
362 0 : if (aModuleName.isEmpty())
363 0 : aModuleName = getDefaultModule_Impl();
364 :
365 0 : aHelpURL.append(aModuleName);
366 :
367 0 : if ( aCommandURL.isEmpty() )
368 0 : aHelpURL.append("/start");
369 : else
370 : {
371 0 : aHelpURL.append('/');
372 : aHelpURL.append(rtl::Uri::encode(aCommandURL,
373 : rtl_UriCharClassRelSegment,
374 : rtl_UriEncodeKeepEscapes,
375 0 : RTL_TEXTENCODING_UTF8));
376 :
377 0 : OUStringBuffer aTempURL = aHelpURL;
378 0 : AppendConfigToken( aTempURL, true );
379 0 : bHasAnchor = GetHelpAnchor_Impl(aTempURL.makeStringAndClear(), aAnchor);
380 : }
381 :
382 0 : AppendConfigToken( aHelpURL, true );
383 :
384 0 : if ( bHasAnchor )
385 : {
386 0 : aHelpURL.append('#');
387 0 : aHelpURL.append(aAnchor);
388 : }
389 :
390 0 : return aHelpURL.makeStringAndClear();
391 : }
392 :
393 0 : SfxHelpWindow_Impl* impl_createHelp(Reference< XFrame2 >& rHelpTask ,
394 : Reference< XFrame >& rHelpContent)
395 : {
396 0 : Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
397 :
398 : // otherwise - create new help task
399 : Reference< XFrame2 > xHelpTask(
400 0 : xDesktop->findFrame( "OFFICE_HELP_TASK", FrameSearchFlag::TASKS | FrameSearchFlag::CREATE),
401 0 : UNO_QUERY);
402 0 : if (!xHelpTask.is())
403 0 : return 0;
404 :
405 : // create all internal windows and sub frames ...
406 0 : Reference< ::com::sun::star::awt::XWindow > xParentWindow = xHelpTask->getContainerWindow();
407 0 : Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow );
408 0 : SfxHelpWindow_Impl* pHelpWindow = new SfxHelpWindow_Impl( xHelpTask, pParentWindow, WB_DOCKBORDER );
409 0 : Reference< ::com::sun::star::awt::XWindow > xHelpWindow = VCLUnoHelper::GetInterface( pHelpWindow );
410 :
411 0 : Reference< XFrame > xHelpContent;
412 0 : if (xHelpTask->setComponent( xHelpWindow, Reference< XController >() ))
413 : {
414 : // Customize UI ...
415 0 : xHelpTask->setName("OFFICE_HELP_TASK");
416 :
417 0 : Reference< XPropertySet > xProps(xHelpTask, UNO_QUERY);
418 0 : if (xProps.is())
419 0 : xProps->setPropertyValue(
420 : "Title",
421 0 : makeAny(SfxResId(STR_HELP_WINDOW_TITLE).toString()));
422 :
423 0 : pHelpWindow->setContainerWindow( xParentWindow );
424 0 : xParentWindow->setVisible(sal_True);
425 0 : xHelpWindow->setVisible(sal_True);
426 :
427 : // This sub frame is created internally (if we called new SfxHelpWindow_Impl() ...)
428 : // It should exist :-)
429 0 : xHelpContent = xHelpTask->findFrame(OUString("OFFICE_HELP"), FrameSearchFlag::CHILDREN);
430 : }
431 :
432 0 : if (!xHelpContent.is())
433 : {
434 0 : delete pHelpWindow;
435 0 : return NULL;
436 : }
437 :
438 0 : xHelpContent->setName("OFFICE_HELP");
439 :
440 0 : rHelpTask = xHelpTask;
441 0 : rHelpContent = xHelpContent;
442 0 : return pHelpWindow;
443 : }
444 :
445 0 : OUString SfxHelp::GetHelpText( const OUString& aCommandURL, const Window* pWindow )
446 : {
447 0 : OUString sModuleName = GetHelpModuleName_Impl();
448 0 : OUString sHelpText = SfxHelp_Impl::GetHelpText( aCommandURL, sModuleName );
449 :
450 0 : OString aNewHelpId;
451 :
452 0 : if (pWindow && sHelpText.isEmpty())
453 : {
454 : // no help text found -> try with parent help id.
455 0 : Window* pParent = pWindow->GetParent();
456 0 : while ( pParent )
457 : {
458 0 : aNewHelpId = pParent->GetHelpId();
459 0 : sHelpText = SfxHelp_Impl::GetHelpText( OStringToOUString(aNewHelpId, RTL_TEXTENCODING_UTF8), sModuleName );
460 0 : if (!sHelpText.isEmpty())
461 0 : pParent = NULL;
462 : else
463 0 : pParent = pParent->GetParent();
464 : }
465 :
466 0 : if (bIsDebug && sHelpText.isEmpty())
467 0 : aNewHelpId = OString();
468 : }
469 :
470 : // add some debug information?
471 0 : if ( bIsDebug )
472 : {
473 0 : sHelpText += "\n-------------\n";
474 0 : sHelpText += sModuleName;
475 0 : sHelpText += ": ";
476 0 : sHelpText += aCommandURL;
477 0 : if ( !aNewHelpId.isEmpty() )
478 : {
479 0 : sHelpText += " - ";
480 0 : sHelpText += OStringToOUString(aNewHelpId, RTL_TEXTENCODING_UTF8);
481 : }
482 : }
483 :
484 0 : return sHelpText;
485 : }
486 :
487 : /// Check for built-in help
488 0 : static bool impl_hasHelpInstalled( const OUString &rLang = OUString() )
489 : {
490 0 : OUStringBuffer aHelpRootURL("vnd.sun.star.help://");
491 0 : AppendConfigToken(aHelpRootURL, true, rLang);
492 0 : std::vector< OUString > aFactories = SfxContentHelper::GetResultSet(aHelpRootURL.makeStringAndClear());
493 :
494 0 : return !aFactories.empty();
495 : }
496 :
497 0 : bool SfxHelp::SearchKeyword( const OUString& rKeyword )
498 : {
499 0 : return Start_Impl( OUString(), NULL, rKeyword );
500 : }
501 :
502 0 : bool SfxHelp::Start( const OUString& rURL, const Window* pWindow )
503 : {
504 0 : return Start_Impl( rURL, pWindow, OUString() );
505 : }
506 :
507 : /// Redirect the vnd.sun.star.help:// urls to http://help.libreoffice.org
508 0 : static bool impl_showOnlineHelp( const OUString& rURL )
509 : {
510 0 : OUString aInternal( "vnd.sun.star.help://" );
511 0 : if ( rURL.getLength() <= aInternal.getLength() || !rURL.startsWith(aInternal) )
512 0 : return false;
513 :
514 0 : OUString aHelpLink( "http://help.libreoffice.org/" );
515 0 : aHelpLink += rURL.copy( aInternal.getLength() );
516 0 : aHelpLink = aHelpLink.replaceAll("%2F","/");
517 : try
518 : {
519 : Reference< XSystemShellExecute > xSystemShell(
520 0 : SystemShellExecute::create(::comphelper::getProcessComponentContext()) );
521 :
522 0 : xSystemShell->execute( aHelpLink, OUString(), SystemShellExecuteFlags::URIS_ONLY );
523 0 : return true;
524 : }
525 0 : catch (const Exception&)
526 : {
527 : }
528 0 : return false;
529 : }
530 :
531 0 : bool SfxHelp::Start_Impl(const OUString& rURL, const Window* pWindow, const OUString& rKeyword)
532 : {
533 0 : OUStringBuffer aHelpRootURL("vnd.sun.star.help://");
534 0 : AppendConfigToken(aHelpRootURL, true);
535 0 : SfxContentHelper::GetResultSet(aHelpRootURL.makeStringAndClear());
536 :
537 : /* rURL may be
538 : - a "real" URL
539 : - a HelpID (formerly a long, now a string)
540 : If rURL is a URL, CreateHelpURL should be called for this URL
541 : If rURL is an arbitrary string, the same should happen, but the URL should be tried out
542 : if it delivers real help content. In case only the Help Error Document is returned, the
543 : parent of the window for that help was called, is asked for its HelpID.
544 : For compatibility reasons this upward search is not implemented for "real" URLs.
545 : Help keyword search now is implemented as own method; in former versions it
546 : was done via Help::Start, but this implementation conflicted with the upward search.
547 : */
548 0 : OUString aHelpURL;
549 0 : INetURLObject aParser( rURL );
550 0 : INetProtocol nProtocol = aParser.GetProtocol();
551 :
552 0 : switch ( nProtocol )
553 : {
554 : case INET_PROT_VND_SUN_STAR_HELP:
555 : // already a vnd.sun.star.help URL -> nothing to do
556 0 : aHelpURL = rURL;
557 0 : break;
558 : default:
559 : {
560 0 : OUString aHelpModuleName( GetHelpModuleName_Impl() );
561 : // no URL, just a HelpID (maybe empty in case of keyword search)
562 0 : aHelpURL = CreateHelpURL_Impl( rURL, aHelpModuleName );
563 :
564 0 : if ( impl_hasHelpInstalled() && pWindow && SfxContentHelper::IsHelpErrorDocument( aHelpURL ) )
565 : {
566 : // no help found -> try with parent help id.
567 0 : Window* pParent = pWindow->GetParent();
568 0 : bool bTriedTabPage = false;
569 0 : while ( pParent )
570 : {
571 0 : OString aHelpId = pParent->GetHelpId();
572 0 : aHelpURL = CreateHelpURL( OStringToOUString(aHelpId, RTL_TEXTENCODING_UTF8), aHelpModuleName );
573 0 : if ( !SfxContentHelper::IsHelpErrorDocument( aHelpURL ) )
574 : {
575 0 : break;
576 : }
577 : else
578 : {
579 0 : pParent = pParent->GetParent();
580 0 : if (!pParent)
581 : {
582 : // create help url of start page ( helpid == 0 -> start page)
583 0 : aHelpURL = CreateHelpURL( OUString(), aHelpModuleName );
584 : }
585 0 : else if (pParent->IsDialog() && !bTriedTabPage)
586 : {
587 : //During help fallback, before we ask a dialog for its help
588 : //see if it has a TabControl and ask the active tab of
589 : //that for help
590 0 : bTriedTabPage = true;
591 0 : Dialog *pDialog = ((Dialog*)pParent);
592 0 : TabControl *pCtrl = pDialog->hasBuilder() ? pDialog->get<TabControl>("tabcontrol") : NULL;
593 0 : TabPage* pTabPage = pCtrl ? pCtrl->GetTabPage(pCtrl->GetCurPageId()) : NULL;
594 0 : Window *pTabChild = pTabPage ? pTabPage->GetWindow(WINDOW_FIRSTCHILD) : NULL;
595 0 : if (pTabChild)
596 0 : pParent = pTabChild;
597 : }
598 : }
599 0 : }
600 : }
601 0 : break;
602 : }
603 : }
604 :
605 0 : if ( !impl_hasHelpInstalled() )
606 : {
607 0 : if ( impl_showOnlineHelp( aHelpURL ) )
608 0 : return true;
609 :
610 0 : NoHelpErrorBox aErrBox( const_cast< Window* >( pWindow ) );
611 0 : aErrBox.Execute();
612 0 : return false;
613 : }
614 :
615 0 : Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
616 :
617 : // check if help window is still open
618 : // If not, create a new one and return access directly to the internal sub frame showing the help content
619 : // search must be done here; search one desktop level could return an arbitraty frame
620 : Reference< XFrame2 > xHelp(
621 0 : xDesktop->findFrame( "OFFICE_HELP_TASK", FrameSearchFlag::CHILDREN),
622 0 : UNO_QUERY);
623 0 : Reference< XFrame > xHelpContent = xDesktop->findFrame(
624 : OUString("OFFICE_HELP"),
625 0 : FrameSearchFlag::CHILDREN);
626 :
627 0 : SfxHelpWindow_Impl* pHelpWindow = 0;
628 0 : if (!xHelp.is())
629 0 : pHelpWindow = impl_createHelp(xHelp, xHelpContent);
630 : else
631 0 : pHelpWindow = (SfxHelpWindow_Impl*)VCLUnoHelper::GetWindow(xHelp->getComponentWindow());
632 0 : if (!xHelp.is() || !xHelpContent.is() || !pHelpWindow)
633 0 : return false;
634 :
635 : #ifdef DBG_UTIL
636 : OStringBuffer aTmp("SfxHelp: HelpId = ");
637 : aTmp.append(OUStringToOString(aHelpURL, RTL_TEXTENCODING_UTF8));
638 : OSL_TRACE( aTmp.getStr() );
639 : #endif
640 :
641 0 : pHelpWindow->SetHelpURL( aHelpURL );
642 0 : pHelpWindow->loadHelpContent(aHelpURL);
643 0 : if (!rKeyword.isEmpty())
644 0 : pHelpWindow->OpenKeyword( rKeyword );
645 :
646 0 : Reference < ::com::sun::star::awt::XTopWindow > xTopWindow( xHelp->getContainerWindow(), UNO_QUERY );
647 0 : if ( xTopWindow.is() )
648 0 : xTopWindow->toFront();
649 :
650 0 : return true;
651 : }
652 :
653 0 : OUString SfxHelp::CreateHelpURL(const OUString& aCommandURL, const OUString& rModuleName)
654 : {
655 0 : SfxHelp* pHelp = static_cast< SfxHelp* >(Application::GetHelp());
656 0 : return pHelp ? pHelp->CreateHelpURL_Impl( aCommandURL, rModuleName ) : OUString();
657 : }
658 :
659 0 : OUString SfxHelp::GetDefaultHelpModule()
660 : {
661 0 : return getDefaultModule_Impl();
662 : }
663 :
664 0 : OUString SfxHelp::GetCurrentModuleIdentifier()
665 : {
666 0 : return getCurrentModuleIdentifier_Impl();
667 : }
668 :
669 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|