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