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