1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 //_______________________________________________
32 // includes
33 
34 #include <framework/titlehelper.hxx>
35 #include <services.h>
36 #include <properties.h>
37 
38 #include <com/sun/star/frame/UntitledNumbersConst.hpp>
39 #include <com/sun/star/frame/XStorable.hpp>
40 #include <com/sun/star/frame/XModuleManager.hpp>
41 #include <com/sun/star/container/XNameAccess.hpp>
42 #include <com/sun/star/document/XEventBroadcaster.hpp>
43 #include <com/sun/star/beans/XMaterialHolder.hpp>
44 
45 #include <unotools/configmgr.hxx>
46 #include <unotools/bootstrap.hxx>
47 #include <comphelper/sequenceashashmap.hxx>
48 #include <rtl/ustrbuf.hxx>
49 #include <osl/mutex.hxx>
50 #include <tools/urlobj.hxx>
51 
52 //_______________________________________________
53 // namespace
54 
55 namespace framework{
56 
57 namespace css = ::com::sun::star;
58 
59 //_______________________________________________
60 // definitions
61 
62 static const ::rtl::OUString ERRMSG_INVALID_COMPONENT_PARAM = ::rtl::OUString::createFromAscii("NULL as component reference not allowed.");
63 static const ::rtl::OUString ERRMSG_INVALID_NUMBER_PARAM    = ::rtl::OUString::createFromAscii("Special valkud INVALID_NUMBER not allowed as input parameter.");
64 
65 //-----------------------------------------------
66 TitleHelper::TitleHelper(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
67     : ::cppu::BaseMutex ()
68     , m_xSMGR           (xSMGR)
69     , m_xOwner          ()
70     , m_xUntitledNumbers()
71     , m_xSubTitle       ()
72     , m_bExternalTitle  (sal_False)
73     , m_sTitle          ()
74     , m_nLeasedNumber   (css::frame::UntitledNumbersConst::INVALID_NUMBER)
75     , m_aListener       (m_aMutex)
76 {
77 }
78 
79 //-----------------------------------------------
80 TitleHelper::~TitleHelper()
81 {
82 }
83 
84 //-----------------------------------------------
85 void TitleHelper::setOwner(const css::uno::Reference< css::uno::XInterface >& xOwner)
86 {
87     // SYNCHRONIZED ->
88     ::osl::ResettableMutexGuard aLock(m_aMutex);
89 
90         m_xOwner = xOwner;
91 
92     aLock.clear ();
93     // <- SYNCHRONIZED
94 
95     css::uno::Reference< css::frame::XModel > xModel(xOwner, css::uno::UNO_QUERY);
96     if (xModel.is ())
97     {
98         impl_startListeningForModel (xModel);
99         return;
100     }
101 
102     css::uno::Reference< css::frame::XController > xController(xOwner, css::uno::UNO_QUERY);
103     if (xController.is ())
104     {
105         impl_startListeningForController (xController);
106         return;
107     }
108 
109     css::uno::Reference< css::frame::XFrame > xFrame(xOwner, css::uno::UNO_QUERY);
110     if (xFrame.is ())
111     {
112         impl_startListeningForFrame (xFrame);
113         return;
114     }
115 }
116 
117 //-----------------------------------------------
118 ::rtl::OUString SAL_CALL TitleHelper::getTitle()
119     throw (css::uno::RuntimeException)
120 {
121     // SYNCHRONIZED ->
122     ::osl::ResettableMutexGuard aLock(m_aMutex);
123 
124         // An external title will win always and disable all internal logic about
125         // creating/using a title value.
126         // Even an empty string will be accepted as valid title !
127         if (m_bExternalTitle)
128             return m_sTitle;
129 
130         // Title seams to be up-to-date. Return it directly.
131         if (m_sTitle.getLength() > 0)
132             return m_sTitle;
133 
134         // Title seams to be unused till now ... do bootstraping
135         impl_updateTitle ();
136 
137         return m_sTitle;
138 
139     // <- SYNCHRONIZED
140 }
141 
142 //-----------------------------------------------
143 void TitleHelper::connectWithUntitledNumbers (const css::uno::Reference< css::frame::XUntitledNumbers >& xNumbers)
144 {
145     // SYNCHRONIZED ->
146     ::osl::ResettableMutexGuard aLock(m_aMutex);
147 
148         m_xUntitledNumbers = xNumbers;
149 
150     // <- SYNCHRONIZED
151 }
152 
153 //-----------------------------------------------
154 void SAL_CALL TitleHelper::setTitle(const ::rtl::OUString& sTitle)
155     throw (css::uno::RuntimeException)
156 {
157     // SYNCHRONIZED ->
158     ::osl::ResettableMutexGuard aLock(m_aMutex);
159 
160         m_bExternalTitle = sal_True;
161         m_sTitle         = sTitle;
162 
163     aLock.clear ();
164     // <- SYNCHRONIZED
165 
166     impl_sendTitleChangedEvent ();
167 }
168 
169 //-----------------------------------------------
170 void SAL_CALL TitleHelper::addTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener)
171     throw (css::uno::RuntimeException)
172 {
173     // container is threadsafe by himself
174     m_aListener.addInterface( ::getCppuType( (const css::uno::Reference< css::frame::XTitleChangeListener >*)NULL ), xListener );
175 }
176 
177 //-----------------------------------------------
178 void SAL_CALL TitleHelper::removeTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener)
179     throw (css::uno::RuntimeException)
180 {
181     // container is threadsafe by himself
182     m_aListener.removeInterface( ::getCppuType( (const css::uno::Reference< css::frame::XTitleChangeListener >*)NULL ), xListener );
183 }
184 
185 //-----------------------------------------------
186 void SAL_CALL TitleHelper::titleChanged(const css::frame::TitleChangedEvent& aEvent)
187     throw (css::uno::RuntimeException)
188 {
189     // SYNCHRONIZED ->
190     ::osl::ResettableMutexGuard aLock(m_aMutex);
191 
192         css::uno::Reference< css::frame::XTitle > xSubTitle(m_xSubTitle.get (), css::uno::UNO_QUERY);
193 
194     aLock.clear ();
195     // <- SYNCHRONIZED
196 
197     if (aEvent.Source != xSubTitle)
198         return;
199 
200     impl_updateTitle ();
201 }
202 
203 //-----------------------------------------------
204 void SAL_CALL TitleHelper::notifyEvent(const css::document::EventObject& aEvent)
205     throw (css::uno::RuntimeException)
206 {
207     if ( ! aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnSaveAsDone")
208       && ! aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnTitleChanged"))
209         return;
210 
211     // SYNCHRONIZED ->
212     ::osl::ResettableMutexGuard aLock(m_aMutex);
213 
214         css::uno::Reference< css::frame::XModel > xOwner(m_xOwner.get (), css::uno::UNO_QUERY);
215 
216     aLock.clear ();
217     // <- SYNCHRONIZED
218 
219     if (
220          aEvent.Source != xOwner ||
221          (aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnTitleChanged") && !xOwner.is())
222        )
223     {
224         return;
225     }
226 
227     impl_updateTitle ();
228 }
229 
230 //-----------------------------------------------
231 void SAL_CALL TitleHelper::frameAction(const css::frame::FrameActionEvent& aEvent)
232     throw(css::uno::RuntimeException)
233 {
234     // SYNCHRONIZED ->
235     ::osl::ResettableMutexGuard aLock(m_aMutex);
236 
237         css::uno::Reference< css::frame::XFrame > xOwner(m_xOwner.get (), css::uno::UNO_QUERY);
238 
239     aLock.clear ();
240     // <- SYNCHRONIZED
241 
242 	if (aEvent.Source != xOwner)
243 		return;
244 
245     // we are interested on events only, which must trigger a title bar update
246     // because component was changed.
247     if (
248         (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED  ) ||
249         (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) ||
250         (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
251        )
252     {
253 		impl_updateListeningForFrame (xOwner);
254 		impl_updateTitle ();
255     }
256 }
257 
258 //-----------------------------------------------
259 void SAL_CALL TitleHelper::disposing(const css::lang::EventObject& aEvent)
260     throw (css::uno::RuntimeException)
261 {
262     // SYNCHRONIZED ->
263     ::osl::ResettableMutexGuard aLock(m_aMutex);
264         css::uno::Reference< css::uno::XInterface >         xOwner        (m_xOwner.get()          , css::uno::UNO_QUERY);
265         css::uno::Reference< css::frame::XUntitledNumbers > xNumbers      (m_xUntitledNumbers.get(), css::uno::UNO_QUERY);
266         ::sal_Int32                                         nLeasedNumber = m_nLeasedNumber;
267     aLock.clear ();
268     // <- SYNCHRONIZED
269 
270     if ( ! xOwner.is ())
271         return;
272 
273     if (xOwner != aEvent.Source)
274         return;
275 
276     if (
277         (xNumbers.is ()                                                   ) &&
278         (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER)
279        )
280        xNumbers->releaseNumber (nLeasedNumber);
281 
282     // SYNCHRONIZED ->
283     aLock.reset ();
284 
285          m_sTitle        = ::rtl::OUString ();
286          m_nLeasedNumber = css::frame::UntitledNumbersConst::INVALID_NUMBER;
287 
288     aLock.clear ();
289     // <- SYNCHRONIZED
290 
291     impl_sendTitleChangedEvent ();
292 }
293 
294 //-----------------------------------------------
295 void TitleHelper::impl_sendTitleChangedEvent ()
296 {
297     // SYNCHRONIZED ->
298     ::osl::ResettableMutexGuard aLock(m_aMutex);
299 
300         css::frame::TitleChangedEvent aEvent(m_xOwner.get (), m_sTitle);
301 
302     aLock.clear ();
303     // <- SYNCHRONIZED
304 
305     ::cppu::OInterfaceContainerHelper* pContainer = m_aListener.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTitleChangeListener >*) NULL ) );
306 	if ( ! pContainer)
307         return;
308 
309     ::cppu::OInterfaceIteratorHelper pIt( *pContainer );
310     while ( pIt.hasMoreElements() )
311     {
312         try
313         {
314             ((css::frame::XTitleChangeListener*)pIt.next())->titleChanged( aEvent );
315         }
316         catch(const css::uno::Exception&)
317         {
318             pIt.remove();
319         }
320     }
321 }
322 
323 //-----------------------------------------------
324 void TitleHelper::impl_updateTitle ()
325 {
326     // SYNCHRONIZED ->
327     ::osl::ResettableMutexGuard aLock(m_aMutex);
328 
329         css::uno::Reference< css::frame::XModel >      xModel     (m_xOwner.get(), css::uno::UNO_QUERY);
330         css::uno::Reference< css::frame::XController > xController(m_xOwner.get(), css::uno::UNO_QUERY);
331         css::uno::Reference< css::frame::XFrame >      xFrame     (m_xOwner.get(), css::uno::UNO_QUERY);
332 
333     aLock.clear ();
334     // <- SYNCHRONIZED
335 
336     if (xModel.is ())
337     {
338         impl_updateTitleForModel (xModel);
339         return;
340     }
341 
342     if (xController.is ())
343     {
344         impl_updateTitleForController (xController);
345         return;
346     }
347 
348     if (xFrame.is ())
349     {
350         impl_updateTitleForFrame (xFrame);
351         return;
352     }
353 }
354 
355 //-----------------------------------------------
356 void TitleHelper::impl_updateTitleForModel (const css::uno::Reference< css::frame::XModel >& xModel)
357 {
358     // SYNCHRONIZED ->
359     ::osl::ResettableMutexGuard aLock(m_aMutex);
360 
361         // external title wont be updated internaly !
362         // It has to be set from outside new.
363         if (m_bExternalTitle)
364             return;
365 
366         css::uno::Reference< css::uno::XInterface >         xOwner        (m_xOwner.get()          , css::uno::UNO_QUERY);
367         css::uno::Reference< css::frame::XUntitledNumbers > xNumbers      (m_xUntitledNumbers.get(), css::uno::UNO_QUERY);
368         ::sal_Int32                                         nLeasedNumber = m_nLeasedNumber;
369 
370     aLock.clear ();
371     // <- SYNCHRONIZED
372 
373     if (
374         ( ! xOwner.is    ()) ||
375         ( ! xNumbers.is  ()) ||
376         ( ! xModel.is    ())
377        )
378         return;
379 
380     ::rtl::OUString sTitle;
381     ::rtl::OUString sURL  ;
382 
383     css::uno::Reference< css::frame::XStorable > xURLProvider(xModel , css::uno::UNO_QUERY);
384     if (xURLProvider.is())
385         sURL = xURLProvider->getLocation ();
386 
387     if (sURL.getLength () > 0)
388     {
389         sTitle = impl_convertURL2Title(sURL);
390         if (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER)
391             xNumbers->releaseNumber (nLeasedNumber);
392 		nLeasedNumber = css::frame::UntitledNumbersConst::INVALID_NUMBER;
393     }
394     else
395     {
396         if (nLeasedNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER)
397             nLeasedNumber = xNumbers->leaseNumber (xOwner);
398 
399         ::rtl::OUStringBuffer sNewTitle(256);
400         sNewTitle.append (xNumbers->getUntitledPrefix ());
401         if (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER)
402             sNewTitle.append ((::sal_Int32)nLeasedNumber);
403         else
404             sNewTitle.appendAscii ("?");
405 
406         sTitle = sNewTitle.makeStringAndClear ();
407     }
408 
409     // SYNCHRONIZED ->
410     aLock.reset ();
411 
412     // WORKAROUND: the notification is currently sent always,
413     //             can be changed after shared mode is supported per UNO API
414     sal_Bool bChanged        = sal_True; // (! m_sTitle.equals(sTitle));
415 
416              m_sTitle        = sTitle;
417              m_nLeasedNumber = nLeasedNumber;
418 
419     aLock.clear ();
420     // <- SYNCHRONIZED
421 
422     if (bChanged)
423         impl_sendTitleChangedEvent ();
424 }
425 
426 //-----------------------------------------------
427 void TitleHelper::impl_updateTitleForController (const css::uno::Reference< css::frame::XController >& xController)
428 {
429     // SYNCHRONIZED ->
430     ::osl::ResettableMutexGuard aLock(m_aMutex);
431 
432         // external title wont be updated internaly !
433         // It has to be set from outside new.
434         if (m_bExternalTitle)
435             return;
436 
437         css::uno::Reference< css::uno::XInterface >         xOwner        (m_xOwner.get()          , css::uno::UNO_QUERY);
438         css::uno::Reference< css::frame::XUntitledNumbers > xNumbers      (m_xUntitledNumbers.get(), css::uno::UNO_QUERY);
439         ::sal_Int32                                         nLeasedNumber = m_nLeasedNumber;
440 
441     aLock.clear ();
442     // <- SYNCHRONIZED
443 
444     if (
445         ( ! xOwner.is      ()) ||
446         ( ! xNumbers.is    ()) ||
447         ( ! xController.is ())
448        )
449         return;
450 
451     ::rtl::OUStringBuffer sTitle(256);
452 
453     if (nLeasedNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER)
454         nLeasedNumber = xNumbers->leaseNumber (xOwner);
455 
456     css::uno::Reference< css::frame::XTitle > xModelTitle(xController->getModel (), css::uno::UNO_QUERY);
457     if (!xModelTitle.is ())
458         xModelTitle.set(xController, css::uno::UNO_QUERY);
459     if (xModelTitle.is ())
460     {
461         sTitle.append      (xModelTitle->getTitle ());
462         if ( nLeasedNumber > 1 )
463         {
464             sTitle.appendAscii (" : ");
465             sTitle.append      ((::sal_Int32)nLeasedNumber);
466         }
467     }
468     else
469     {
470         sTitle.append (xNumbers->getUntitledPrefix ());
471         if ( nLeasedNumber > 1 )
472         {
473             sTitle.append ((::sal_Int32)nLeasedNumber  );
474         }
475     }
476 
477     // SYNCHRONIZED ->
478     aLock.reset ();
479 
480         ::rtl::OUString sNewTitle       = sTitle.makeStringAndClear ();
481         sal_Bool        bChanged        = (! m_sTitle.equals(sNewTitle));
482                         m_sTitle        = sNewTitle;
483                         m_nLeasedNumber = nLeasedNumber;
484 
485     aLock.clear ();
486     // <- SYNCHRONIZED
487 
488     if (bChanged)
489         impl_sendTitleChangedEvent ();
490 }
491 
492 //-----------------------------------------------
493 void TitleHelper::impl_updateTitleForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame)
494 {
495     if ( ! xFrame.is ())
496         return;
497 
498     // SYNCHRONIZED ->
499     ::osl::ResettableMutexGuard aLock(m_aMutex);
500 
501         // external title wont be updated internaly !
502         // It has to be set from outside new.
503         if (m_bExternalTitle)
504             return;
505 
506     aLock.clear ();
507     // <- SYNCHRONIZED
508 
509     css::uno::Reference< css::uno::XInterface > xComponent;
510     xComponent = xFrame->getController ();
511     if ( ! xComponent.is ())
512         xComponent = xFrame->getComponentWindow ();
513 
514     ::rtl::OUStringBuffer sTitle (256);
515 
516     impl_appendComponentTitle   (sTitle, xComponent);
517     impl_appendProductName      (sTitle);
518     impl_appendModuleName       (sTitle);
519     impl_appendProductExtension (sTitle);
520     //impl_appendEvalVersion      (sTitle);
521     impl_appendDebugVersion     (sTitle);
522 
523     // SYNCHRONIZED ->
524     aLock.reset ();
525 
526         ::rtl::OUString sNewTitle = sTitle.makeStringAndClear ();
527         sal_Bool        bChanged  = (! m_sTitle.equals(sNewTitle));
528                         m_sTitle  = sNewTitle;
529 
530     aLock.clear ();
531     // <- SYNCHRONIZED
532 
533     if (bChanged)
534         impl_sendTitleChangedEvent ();
535 }
536 
537 //*****************************************************************************************************************
538 void TitleHelper::impl_appendComponentTitle (      ::rtl::OUStringBuffer&                       sTitle    ,
539                                              const css::uno::Reference< css::uno::XInterface >& xComponent)
540 {
541     css::uno::Reference< css::frame::XTitle > xTitle(xComponent, css::uno::UNO_QUERY);
542 
543 	// Note: Title has to be used (even if it's empty) if the right interface is supported.
544     if (xTitle.is ())
545         sTitle.append (xTitle->getTitle ());
546 }
547 
548 //*****************************************************************************************************************
549 void TitleHelper::impl_appendProductName (::rtl::OUStringBuffer& sTitle)
550 {
551     ::rtl::OUString sProductName;
552     ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTNAME) >>= sProductName;
553 
554     if (sProductName.getLength ())
555     {
556         if (sTitle.getLength() > 0)
557             sTitle.appendAscii (" - ");
558 
559         sTitle.append (sProductName);
560     }
561 }
562 
563 //*****************************************************************************************************************
564 void TitleHelper::impl_appendProductExtension (::rtl::OUStringBuffer& sTitle)
565 {
566     ::rtl::OUString sProductExtension;
567     ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTEXTENSION) >>= sProductExtension;
568 
569     if (sProductExtension.getLength ())
570     {
571         sTitle.appendAscii (" ");
572         sTitle.append      (sProductExtension);
573     }
574 }
575 
576 //*****************************************************************************************************************
577 void TitleHelper::impl_appendModuleName (::rtl::OUStringBuffer& sTitle)
578 {
579     // SYNCHRONIZED ->
580     ::osl::ResettableMutexGuard aLock(m_aMutex);
581 
582         css::uno::Reference< css::uno::XInterface >            xOwner = m_xOwner.get();
583         css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR  = m_xSMGR;
584 
585     aLock.clear ();
586     // <- SYNCHRONIZED
587 
588     try
589     {
590         css::uno::Reference< css::frame::XModuleManager > xModuleManager(
591             xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
592             css::uno::UNO_QUERY_THROW);
593 
594         css::uno::Reference< css::container::XNameAccess > xConfig(
595             xModuleManager,
596             css::uno::UNO_QUERY_THROW);
597 
598         const ::rtl::OUString                 sID     = xModuleManager->identify(xOwner);
599               ::comphelper::SequenceAsHashMap lProps  = xConfig->getByName (sID);
600         const ::rtl::OUString                 sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, ::rtl::OUString());
601 
602         // An UIname property is an optional value !
603         // So please add it to the title in case it does realy exists only.
604         if (sUIName.getLength() > 0)
605         {
606             sTitle.appendAscii (" "    );
607             sTitle.append      (sUIName);
608         }
609     }
610     catch(const css::uno::Exception&)
611     {}
612 }
613 
614 //*****************************************************************************************************************
615 #ifdef DBG_UTIL
616 void TitleHelper::impl_appendDebugVersion (::rtl::OUStringBuffer& sTitle)
617 {
618         ::rtl::OUString sDefault ;
619 		::rtl::OUString sVersion = ::utl::Bootstrap::getBuildIdData( sDefault );
620 
621 		sTitle.appendAscii (" ["    );
622 		sTitle.append      (sVersion);
623 		sTitle.appendAscii ("]"     );
624 }
625 #else
626 void TitleHelper::impl_appendDebugVersion (::rtl::OUStringBuffer&)
627 {
628 }
629 #endif
630 
631 //*****************************************************************************************************************
632 void TitleHelper::impl_appendEvalVersion (::rtl::OUStringBuffer& /*sTitle*/)
633 {
634     // SYNCHRONIZED ->
635  //   ::osl::ResettableMutexGuard aLock(m_aMutex);
636  //   css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ;
637 	//aLock.clear ();
638 	//// <- SYNCHRONIZED
639 
640 	//css::uno::Reference< css::beans::XMaterialHolder > xHolder(
641  //       xSMGR->createInstance(SERVICENAME_TABREG),
642 	//	css::uno::UNO_QUERY);
643 
644  //   if ( ! xHolder.is())
645 	//	return;
646 
647 	//	  ::comphelper::SequenceAsHashMap aMaterial(xHolder->getMaterial());
648 	//const ::rtl::OUString				  sEvalTitle = aMaterial.getUnpackedValueOrDefault(TABREG_PROPNAME_TITLE, ::rtl::OUString());
649 
650 	//if (sEvalTitle.getLength())
651 	//{
652 	//	sTitle.appendAscii (" "		  );
653 	//	sTitle.append	   (sEvalTitle);
654 	//}
655 }
656 
657 //-----------------------------------------------
658 void TitleHelper::impl_startListeningForModel (const css::uno::Reference< css::frame::XModel >& xModel)
659 {
660     css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xModel, css::uno::UNO_QUERY);
661     if ( ! xBroadcaster.is ())
662         return;
663 
664     xBroadcaster->addEventListener (static_cast< css::document::XEventListener* >(this));
665 }
666 
667 //-----------------------------------------------
668 void TitleHelper::impl_startListeningForController (const css::uno::Reference< css::frame::XController >& xController)
669 {
670     css::uno::Reference< css::frame::XTitle > xSubTitle(xController->getModel (), css::uno::UNO_QUERY);
671     impl_setSubTitle (xSubTitle);
672 }
673 
674 //-----------------------------------------------
675 void TitleHelper::impl_startListeningForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame)
676 {
677 	xFrame->addFrameActionListener(this  );
678 	impl_updateListeningForFrame  (xFrame);
679 }
680 
681 //-----------------------------------------------
682 void TitleHelper::impl_updateListeningForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame)
683 {
684     css::uno::Reference< css::frame::XTitle > xSubTitle(xFrame->getController (), css::uno::UNO_QUERY);
685     impl_setSubTitle (xSubTitle);
686 }
687 
688 //-----------------------------------------------
689 void TitleHelper::impl_setSubTitle (const css::uno::Reference< css::frame::XTitle >& xSubTitle)
690 {
691     // SYNCHRONIZED ->
692     ::osl::ResettableMutexGuard aLock(m_aMutex);
693 
694         // ignore duplicate calls. Makes outside using of this helper more easy :-)
695         css::uno::Reference< css::frame::XTitle > xOldSubTitle(m_xSubTitle.get(), css::uno::UNO_QUERY);
696         if (xOldSubTitle == xSubTitle)
697             return;
698 
699         m_xSubTitle = xSubTitle;
700 
701     aLock.clear ();
702     // <- SYNCHRONIZED
703 
704     css::uno::Reference< css::frame::XTitleChangeBroadcaster > xOldBroadcaster(xOldSubTitle                                          , css::uno::UNO_QUERY      );
705     css::uno::Reference< css::frame::XTitleChangeBroadcaster > xNewBroadcaster(xSubTitle                                             , css::uno::UNO_QUERY      );
706     css::uno::Reference< css::frame::XTitleChangeListener >    xThis          (static_cast< css::frame::XTitleChangeListener* >(this), css::uno::UNO_QUERY_THROW);
707 
708     if (xOldBroadcaster.is())
709         xOldBroadcaster->removeTitleChangeListener (xThis);
710 
711     if (xNewBroadcaster.is())
712         xNewBroadcaster->addTitleChangeListener (xThis);
713 }
714 
715 //-----------------------------------------------
716 ::rtl::OUString TitleHelper::impl_getSubTitle ()
717 {
718     // SYNCHRONIZED ->
719     ::osl::ResettableMutexGuard aLock(m_aMutex);
720 
721         css::uno::Reference< css::frame::XTitle > xSubTitle(m_xSubTitle.get (), css::uno::UNO_QUERY);
722 
723     aLock.clear ();
724     // <- SYNCHRONIZED
725 
726     if (xSubTitle.is ())
727         return xSubTitle->getTitle ();
728 
729     return ::rtl::OUString ();
730 }
731 
732 //-----------------------------------------------
733 ::rtl::OUString TitleHelper::impl_convertURL2Title(const ::rtl::OUString& sURL)
734 {
735     INetURLObject   aURL (sURL);
736     ::rtl::OUString sTitle;
737 
738     if (aURL.GetProtocol() == INET_PROT_FILE)
739     {
740         if (aURL.HasMark())
741             aURL = INetURLObject(aURL.GetURLNoMark());
742 
743         sTitle = aURL.getName(INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::DECODE_WITH_CHARSET);
744     }
745     else
746     {
747         if (aURL.hasExtension(INetURLObject::LAST_SEGMENT))
748             sTitle = aURL.getName(INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::DECODE_WITH_CHARSET);
749 
750         if ( ! sTitle.getLength() )
751 		    sTitle = aURL.GetHostPort(INetURLObject::DECODE_WITH_CHARSET);
752 
753         if ( ! sTitle.getLength() )
754             sTitle = aURL.GetURLNoPass(INetURLObject::DECODE_WITH_CHARSET);
755     }
756 
757     return sTitle;
758 }
759 
760 } // namespace framework
761