xref: /aoo42x/main/svx/source/unodraw/unoshtxt.cxx (revision f6e50924)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 #include <com/sun/star/uno/XInterface.hpp>
27 #include <vcl/svapp.hxx>
28 
29 #include <svx/unoshtxt.hxx>
30 #include <editeng/unoedhlp.hxx>
31 #include <svl/lstner.hxx>
32 #include <rtl/ref.hxx>
33 #include <osl/mutex.hxx>
34 #include <svl/hint.hxx>
35 #include <svl/style.hxx>
36 #include <svx/svdmodel.hxx>
37 #include <svx/svdoutl.hxx>
38 #include <svx/svdobj.hxx>
39 #include <svx/svdview.hxx>
40 #include <svx/svdetc.hxx>
41 #include <editeng/outliner.hxx>
42 #include <editeng/unoforou.hxx>
43 #include <editeng/unoviwou.hxx>
44 #include <editeng/outlobj.hxx>
45 #include <svx/svdotext.hxx>
46 #include <svx/svdpage.hxx>
47 #include <editeng/editeng.hxx>
48 #include <editeng/editobj.hxx>
49 
50 #include <editeng/unotext.hxx>
51 #include <com/sun/star/linguistic2/XLinguServiceManager.hpp>
52 #include <comphelper/processfactory.hxx>
53 #include <vos/mutex.hxx>
54 #include <svx/sdrpaintwindow.hxx>
55 
56 using namespace ::osl;
57 using namespace ::vos;
58 using namespace ::rtl;
59 
60 using ::com::sun::star::uno::XInterface;
61 
62 namespace css = ::com::sun::star;
63 
64 
65 //------------------------------------------------------------------------
66 // SvxTextEditSourceImpl
67 //------------------------------------------------------------------------
68 
69 /** @descr
70     <p>This class essentially provides the text and view forwarders. If
71     no SdrView is given, this class handles the UNO objects, which are
72     currently not concerned with view issues. In this case,
73     GetViewForwarder() always returns NULL and the underlying
74     EditEngine of the SvxTextForwarder is a background one (i.e. not
75     the official DrawOutliner, but one created exclusively for this
76     object, with no relation to a view).
77     </p>
78 
79     <p>If a SdrView is given at construction time, the caller is
80     responsible for destroying this object when the view becomes
81     invalid (the views cannot notify). If GetViewForwarder(sal_True)
82     is called, the underlying shape is put into edit mode, the view
83     forwarder returned encapsulates the OutlinerView and the next call
84     to GetTextForwarder() yields a forwarder encapsulating the actual
85     DrawOutliner. Thus, changes on that Outliner are immediately
86     reflected on the screen. If the object leaves edit mode, the old
87     behaviour is restored.</p>
88  */
89 class SvxTextEditSourceImpl : public SfxListener, public SfxBroadcaster, public sdr::ObjectUser
90 {
91 private:
92 	oslInterlockedCount	maRefCount;
93 
94 	SdrObject*						mpObject;
95 	SdrText*						mpText;
96 	SdrView*						mpView;
97     const Window*					mpWindow;
98 	SdrModel*						mpModel;
99 	SdrOutliner*					mpOutliner;
100 	SvxOutlinerForwarder*			mpTextForwarder;
101 	SvxDrawOutlinerViewForwarder*	mpViewForwarder;	// if non-NULL, use GetViewModeTextForwarder text forwarder
102 	css::uno::Reference< css::linguistic2::XLinguServiceManager > m_xLinguServiceManager;
103     Point							maTextOffset;
104 	sal_Bool							mbDataValid;
105 	sal_Bool							mbDestroyed;
106 	sal_Bool							mbIsLocked;
107 	sal_Bool							mbNeedsUpdate;
108 	sal_Bool							mbOldUndoMode;
109     sal_Bool							mbForwarderIsEditMode;		// have to reflect that, since ENDEDIT can happen more often
110     sal_Bool							mbShapeIsEditMode;			// #104157# only true, if HINT_BEGEDIT was received
111     sal_Bool							mbNotificationsDisabled;	// prevent EditEngine/Outliner notifications (e.g. when setting up forwarder)
112 
113 	XInterface*						mpOwner;
114 	SvxUnoTextRangeBaseList			maTextRanges;
115 
116     SvxTextForwarder*				GetBackgroundTextForwarder();
117     SvxTextForwarder*				GetEditModeTextForwarder();
118     SvxDrawOutlinerViewForwarder*	CreateViewForwarder();
119 
120     void 							SetupOutliner();
121 
122     sal_Bool						HasView() const { return mpView ? sal_True : sal_False; }
123     sal_Bool						IsEditMode() const
124     								{
125                                         SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
126                                         return mbShapeIsEditMode && pTextObj && pTextObj->IsTextEditActive() ? sal_True : sal_False;
127                                     }
128 
129 	void							dispose();
130 
131 public:
132 	SvxTextEditSourceImpl( SdrObject* pObject, SdrText* pText, XInterface* pOwner );
133 	SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const Window& rWindow );
134 	~SvxTextEditSourceImpl();
135 
136 	void SAL_CALL acquire();
137 	void SAL_CALL release();
138 
139 	virtual void			Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
140 
141 	SvxEditSource*			Clone() const;
142 	SvxTextForwarder*		GetTextForwarder();
143     SvxEditViewForwarder* 	GetEditViewForwarder( sal_Bool );
144 	void					UpdateData();
145 
146 	void addRange( SvxUnoTextRangeBase* pNewRange );
147 	void removeRange( SvxUnoTextRangeBase* pOldRange );
148 	const SvxUnoTextRangeBaseList& getRanges() const;
149 
150 	SdrObject* 				GetSdrObject() const { return mpObject; }
151 
152 	void 					lock();
153 	void 					unlock();
154 
155 	sal_Bool					IsValid() const;
156 
157     Rectangle				GetVisArea();
158     Point					LogicToPixel( const Point&, const MapMode& rMapMode );
159     Point 					PixelToLogic( const Point&, const MapMode& rMapMode );
160 
161     DECL_LINK( NotifyHdl, EENotify* );
162 
163 	virtual void ObjectInDestruction(const SdrObject& rObject);
164 
165 	void ChangeModel( SdrModel* pNewModel );
166 
167     void                    UpdateOutliner();
168 };
169 
170 //------------------------------------------------------------------------
171 
172 SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject* pObject, SdrText* pText, XInterface* pOwner )
173   :	maRefCount		( 0 ),
174     mpObject		( pObject ),
175 	mpText			( pText ),
176 	mpView			( NULL ),
177 	mpWindow		( NULL ),
178 	mpModel			( pObject ? pObject->GetModel() : NULL ),
179 	mpOutliner		( NULL ),
180 	mpTextForwarder	( NULL ),
181 	mpViewForwarder	( NULL ),
182 	mbDataValid		( sal_False ),
183 	mbDestroyed		( sal_False ),
184 	mbIsLocked		( sal_False ),
185 	mbNeedsUpdate	( sal_False ),
186 	mbOldUndoMode	( sal_False ),
187 	mbForwarderIsEditMode ( sal_False ),
188 	mbShapeIsEditMode	  ( sal_False ),
189 	mbNotificationsDisabled ( sal_False ),
190 	mpOwner( pOwner )
191 {
192 	DBG_ASSERT( mpObject, "invalid pObject!" );
193 
194 	if( !mpText )
195 	{
196 		SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
197 		if( pTextObj )
198 			mpText = pTextObj->getText( 0 );
199 	}
200 
201 	if( mpModel )
202 		StartListening( *mpModel );
203 
204 	if( mpObject )
205 		mpObject->AddObjectUser( *this );
206 }
207 
208 //------------------------------------------------------------------------
209 
210 SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const Window& rWindow )
211   :	maRefCount		( 0 ),
212     mpObject		( &rObject ),
213 	mpText			( pText ),
214     mpView			( &rView ),
215     mpWindow		( &rWindow ),
216 	mpModel			( rObject.GetModel() ),
217 	mpOutliner		( NULL ),
218 	mpTextForwarder	( NULL ),
219 	mpViewForwarder	( NULL ),
220 	mbDataValid		( sal_False ),
221 	mbDestroyed		( sal_False ),
222 	mbIsLocked		( sal_False ),
223 	mbNeedsUpdate	( sal_False ),
224 	mbOldUndoMode	( sal_False ),
225 	mbForwarderIsEditMode ( sal_False ),
226     mbShapeIsEditMode	  ( sal_True ),
227 	mbNotificationsDisabled ( sal_False ),
228 	mpOwner(0)
229 {
230 	if( !mpText )
231 	{
232 		SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
233 		if( pTextObj )
234 			mpText = pTextObj->getText( 0 );
235 	}
236 
237 	if( mpModel )
238 		StartListening( *mpModel );
239 	if( mpView )
240 		StartListening( *mpView );
241 	if( mpObject )
242 		mpObject->AddObjectUser( *this );
243 
244     // #104157# Init edit mode state from shape info (IsTextEditActive())
245     mbShapeIsEditMode = IsEditMode();
246 }
247 
248 //------------------------------------------------------------------------
249 
250 SvxTextEditSourceImpl::~SvxTextEditSourceImpl()
251 {
252 	DBG_ASSERT( mbIsLocked == sal_False, "text edit source was not unlocked before dispose!" );
253 	if( mpObject )
254 		mpObject->RemoveObjectUser( *this );
255 
256 	dispose();
257 }
258 
259 //------------------------------------------------------------------------
260 
261 void SvxTextEditSourceImpl::addRange( SvxUnoTextRangeBase* pNewRange )
262 {
263 	if( pNewRange )
264 		if( std::find( maTextRanges.begin(), maTextRanges.end(), pNewRange ) == maTextRanges.end() )
265 			maTextRanges.push_back( pNewRange );
266 }
267 
268 //------------------------------------------------------------------------
269 
270 void SvxTextEditSourceImpl::removeRange( SvxUnoTextRangeBase* pOldRange )
271 {
272 	if( pOldRange )
273 		maTextRanges.remove( pOldRange );
274 }
275 
276 //------------------------------------------------------------------------
277 
278 const SvxUnoTextRangeBaseList& SvxTextEditSourceImpl::getRanges() const
279 {
280 	return maTextRanges;
281 }
282 
283 //------------------------------------------------------------------------
284 
285 void SAL_CALL SvxTextEditSourceImpl::acquire()
286 {
287 	osl_incrementInterlockedCount( &maRefCount );
288 }
289 
290 //------------------------------------------------------------------------
291 
292 void SAL_CALL SvxTextEditSourceImpl::release()
293 {
294 	if( ! osl_decrementInterlockedCount( &maRefCount ) )
295 		delete this;
296 }
297 
298 void SvxTextEditSourceImpl::ChangeModel( SdrModel* pNewModel )
299 {
300 	if( mpModel != pNewModel )
301 	{
302 		if( mpModel )
303 			EndListening( *mpModel );
304 
305 		if( mpOutliner )
306 		{
307 			if( mpModel )
308 				mpModel->disposeOutliner( mpOutliner );
309 			else
310 				delete mpOutliner;
311 			mpOutliner = 0;
312 		}
313 
314 		if( mpView )
315 		{
316 			EndListening( *mpView );
317 			mpView = 0;
318 		}
319 
320 		mpWindow = 0;
321 		m_xLinguServiceManager.clear();
322 		mpOwner = 0;
323 
324 		mpModel = pNewModel;
325 
326 		if( mpTextForwarder )
327 		{
328 	        delete mpTextForwarder;
329 		    mpTextForwarder = 0;
330 		}
331 
332 		if( mpViewForwarder )
333 		{
334 			delete mpViewForwarder;
335 			mpViewForwarder = 0;
336 		}
337 
338 		if( mpModel )
339 			StartListening( *mpModel );
340 	}
341 }
342 
343 //------------------------------------------------------------------------
344 
345 void SvxTextEditSourceImpl::Notify( SfxBroadcaster&, const SfxHint& rHint )
346 {
347     // #i105988 keep reference to this object
348     rtl::Reference< SvxTextEditSourceImpl > xThis( this );
349 
350 	const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
351 	const SvxViewHint* pViewHint = PTR_CAST( SvxViewHint, &rHint );
352 
353     if( pViewHint )
354     {
355         switch( pViewHint->GetHintType() )
356         {
357             case SvxViewHint::SVX_HINT_VIEWCHANGED:
358                 Broadcast( *pViewHint );
359                 break;
360         }
361     }
362 	else if( pSdrHint )
363 	{
364         switch( pSdrHint->GetKind() )
365         {
366             case HINT_OBJCHG:
367             {
368                 mbDataValid = sal_False;						// Text muss neu geholt werden
369 
370                 if( HasView() )
371                 {
372                     // #104157# Update maTextOffset, object has changed
373 					// #105196#, #105203#: Cannot call that // here,
374 					// since TakeTextRect() (called from there) //
375 					// changes outliner content.
376 					// UpdateOutliner();
377 
378                     // #101029# Broadcast object changes, as they might change visible attributes
379                     SvxViewHint aHint(SvxViewHint::SVX_HINT_VIEWCHANGED);
380                     Broadcast( aHint );
381                 }
382                 break;
383             }
384 
385             case HINT_BEGEDIT:
386                 if( mpObject == pSdrHint->GetObject() )
387                 {
388                     // invalidate old forwarder
389                     if( !mbForwarderIsEditMode )
390                     {
391                         delete mpTextForwarder;
392                         mpTextForwarder = NULL;
393                     }
394 
395                     // register as listener - need to broadcast state change messages
396                     if( mpView && mpView->GetTextEditOutliner() )
397                         mpView->GetTextEditOutliner()->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) );
398 
399                     // #104157# Only now we're really in edit mode
400                     mbShapeIsEditMode = sal_True;
401 
402                     Broadcast( *pSdrHint );
403                 }
404                 break;
405 
406             case HINT_ENDEDIT:
407                 if( mpObject == pSdrHint->GetObject() )
408                 {
409                     Broadcast( *pSdrHint );
410 
411                     // #104157# We're no longer in edit mode
412                     mbShapeIsEditMode = sal_False;
413 
414                     // remove as listener - outliner might outlive ourselves
415                     if( mpView && mpView->GetTextEditOutliner() )
416                         mpView->GetTextEditOutliner()->SetNotifyHdl( Link() );
417 
418                     // destroy view forwarder, OutlinerView no longer
419                     // valid (no need for UpdateData(), it's been
420                     // synched on SdrEndTextEdit)
421                     delete mpViewForwarder;
422                     mpViewForwarder = NULL;
423 
424                     // #100424# Invalidate text forwarder, we might
425                     // not be called again before entering edit mode a
426                     // second time! Then, the old outliner might be
427                     // invalid.
428                     if( mbForwarderIsEditMode )
429                     {
430                         mbForwarderIsEditMode = sal_False;
431                         delete mpTextForwarder;
432                         mpTextForwarder = NULL;
433                     }
434                 }
435                 break;
436 
437 			case HINT_MODELCLEARED:
438 				dispose();
439 				break;
440 			default:
441 				break;
442         }
443     }
444 }
445 
446 /* this is a callback from the attached SdrObject when it is actually deleted */
447 void SvxTextEditSourceImpl::ObjectInDestruction(const SdrObject&)
448 {
449 	mpObject = 0;
450 	dispose();
451     Broadcast( SfxSimpleHint( SFX_HINT_DYING ) );
452 }
453 
454 /* unregister at all objects and set all references to 0 */
455 void SvxTextEditSourceImpl::dispose()
456 {
457 	if( mpTextForwarder )
458 	{
459 	    delete mpTextForwarder;
460 		mpTextForwarder = 0;
461 	}
462 
463 	if( mpViewForwarder )
464 	{
465 	    delete mpViewForwarder;
466 		mpViewForwarder = 0;
467 	}
468 
469 	if( mpOutliner )
470 	{
471 		if( mpModel )
472 		{
473 			mpModel->disposeOutliner( mpOutliner );
474 		}
475 		else
476 		{
477 			delete mpOutliner;
478 		}
479 		mpOutliner = 0;
480 	}
481 
482 	if( mpModel )
483 	{
484 		EndListening( *mpModel );
485 		mpModel = 0;
486 	}
487 
488 	if( mpView )
489 	{
490 		EndListening( *mpView );
491         mpView = 0;
492 	}
493 
494 	if( mpObject )
495 	{
496 		mpObject->RemoveObjectUser( *this );
497 		mpObject = 0;
498 	}
499 	mpWindow = 0;
500 }
501 
502 //------------------------------------------------------------------------
503 
504 void SvxTextEditSourceImpl::SetupOutliner()
505 {
506     // #101029#
507     // only for UAA edit source: setup outliner equivalently as in
508     // SdrTextObj::Paint(), such that formatting equals screen
509     // layout
510     if( mpObject && mpOutliner )
511     {
512         SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
513         Rectangle aPaintRect;
514         if( pTextObj )
515         {
516             Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
517             pTextObj->SetupOutlinerFormatting( *mpOutliner, aPaintRect );
518 
519             // #101029# calc text offset from shape anchor
520             maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
521         }
522     }
523 }
524 
525 //------------------------------------------------------------------------
526 
527 void SvxTextEditSourceImpl::UpdateOutliner()
528 {
529     // #104157#
530     // only for UAA edit source: update outliner equivalently as in
531     // SdrTextObj::Paint(), such that formatting equals screen
532     // layout
533     if( mpObject && mpOutliner )
534     {
535         SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
536         Rectangle aPaintRect;
537         if( pTextObj )
538         {
539             Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
540             pTextObj->UpdateOutlinerFormatting( *mpOutliner, aPaintRect );
541 
542             // #101029# calc text offset from shape anchor
543             maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
544         }
545     }
546 }
547 
548 //------------------------------------------------------------------------
549 
550 
551 
552 SvxTextForwarder* SvxTextEditSourceImpl::GetBackgroundTextForwarder()
553 {
554     sal_Bool bCreated = sal_False;
555 
556     // #99840#: prevent EE/Outliner notifications during setup
557     mbNotificationsDisabled = sal_True;
558 
559 	if (!mpTextForwarder)
560 	{
561 		if( mpOutliner == NULL )
562 		{
563 			SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
564 			sal_uInt16 nOutlMode = OUTLINERMODE_TEXTOBJECT;
565 			if( pTextObj && pTextObj->IsTextFrame() && pTextObj->GetTextKind() == OBJ_OUTLINETEXT )
566 				nOutlMode = OUTLINERMODE_OUTLINEOBJECT;
567 
568 			mpOutliner = mpModel->createOutliner( nOutlMode );
569 
570             // #109151# Do the setup after outliner creation, would be useless otherwise
571             if( HasView() )
572             {
573                 // #101029#, #104157# Setup outliner _before_ filling it
574                 SetupOutliner();
575             }
576 
577 			mpOutliner->SetTextObjNoInit( pTextObj );
578 /*
579 			mpOutliner = SdrMakeOutliner( nOutlMode, pModel );
580 			Outliner& aDrawOutliner = pModel->GetDrawOutliner();
581 			mpOutliner->SetCalcFieldValueHdl( aDrawOutliner.GetCalcFieldValueHdl() );
582 */
583 			if( mbIsLocked )
584 			{
585 				((EditEngine*)&(mpOutliner->GetEditEngine()))->SetUpdateMode( sal_False );
586 				mbOldUndoMode = ((EditEngine*)&(mpOutliner->GetEditEngine()))->IsUndoEnabled();
587 				((EditEngine*)&(mpOutliner->GetEditEngine()))->EnableUndo( sal_False );
588 			}
589 
590 // -
591 			if ( !m_xLinguServiceManager.is() )
592 			{
593 				css::uno::Reference< css::lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
594 				m_xLinguServiceManager = css::uno::Reference< css::linguistic2::XLinguServiceManager >(
595 					xMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.linguistic2.LinguServiceManager" ))), css::uno::UNO_QUERY );
596 			}
597 
598 			if ( m_xLinguServiceManager.is() )
599 			{
600 				css::uno::Reference< css::linguistic2::XHyphenator > xHyphenator( m_xLinguServiceManager->getHyphenator(), css::uno::UNO_QUERY );
601 				if( xHyphenator.is() )
602 					mpOutliner->SetHyphenator( xHyphenator );
603 			}
604 // -
605 		}
606 
607 
608 		mpTextForwarder = new SvxOutlinerForwarder( *mpOutliner, (mpObject->GetObjInventor() == SdrInventor) && (mpObject->GetObjIdentifier() == OBJ_OUTLINETEXT) );
609         // delay listener subscription and UAA initialization until Outliner is fully setup
610         bCreated = sal_True;
611 
612         mbForwarderIsEditMode = sal_False;
613 	}
614 
615 	if( mpObject && mpText && !mbDataValid && mpObject->IsInserted() && mpObject->GetPage() )
616 	{
617 		mpTextForwarder->flushCache();
618 
619 		OutlinerParaObject* pOutlinerParaObject = NULL;
620 		SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
621 		if( pTextObj && pTextObj->getActiveText() == mpText )
622 			pOutlinerParaObject = pTextObj->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
623 		bool bOwnParaObj(false);
624 
625 		if( pOutlinerParaObject )
626 			bOwnParaObj = true;	// text edit active
627 		else
628 			pOutlinerParaObject = mpText->GetOutlinerParaObject();
629 
630 		if( pOutlinerParaObject && ( bOwnParaObj || !mpObject->IsEmptyPresObj() || mpObject->GetPage()->IsMasterPage() ) )
631 		{
632 			mpOutliner->SetText( *pOutlinerParaObject );
633 
634 			// #91254# put text to object and set EmptyPresObj to FALSE
635 			if( mpText && bOwnParaObj && pOutlinerParaObject && mpObject->IsEmptyPresObj() && pTextObj->IsRealyEdited() )
636 			{
637 				mpObject->SetEmptyPresObj( sal_False );
638 				static_cast< SdrTextObj* >( mpObject)->NbcSetOutlinerParaObjectForText( pOutlinerParaObject, mpText );
639 
640                 // #i103982# Here, due to mpObject->NbcSetOutlinerParaObjectForText, we LOSE ownership of the
641                 // OPO, so do NOT delete it when leaving this method (!)
642                 bOwnParaObj = false;
643 			}
644 		}
645 		else
646 		{
647 			sal_Bool bVertical = pOutlinerParaObject ? pOutlinerParaObject->IsVertical() : sal_False;
648 
649 			// set objects style sheet on empty outliner
650 			SfxStyleSheetPool* pPool = (SfxStyleSheetPool*)mpObject->GetModel()->GetStyleSheetPool();
651 			if( pPool )
652 				mpOutliner->SetStyleSheetPool( pPool );
653 
654 			SfxStyleSheet* pStyleSheet = mpObject->GetPage()->GetTextStyleSheetForObject( mpObject );
655 			if( pStyleSheet )
656 				mpOutliner->SetStyleSheet( 0, pStyleSheet );
657 
658 			if( bVertical )
659 				mpOutliner->SetVertical( sal_True );
660 		}
661 
662 		// evtually we have to set the border attributes
663 		if (mpOutliner->GetParagraphCount()==1)
664 		{
665 			// if we only have one paragraph we check if it is empty
666 			XubString aStr( mpOutliner->GetText( mpOutliner->GetParagraph( 0 ) ) );
667 
668 			if(!aStr.Len())
669 			{
670 				// its empty, so we have to force the outliner to initialise itself
671 				mpOutliner->SetText( String(), mpOutliner->GetParagraph( 0 ) );
672 
673 				if(mpObject->GetStyleSheet())
674 					mpOutliner->SetStyleSheet( 0, mpObject->GetStyleSheet());
675 			}
676 		}
677 
678 		mbDataValid = sal_True;
679 
680         if( bOwnParaObj )
681             delete pOutlinerParaObject;
682 	}
683 
684     if( bCreated && mpOutliner && HasView() )
685     {
686         // register as listener - need to broadcast state change messages
687         // registration delayed until outliner is completely set up
688         mpOutliner->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) );
689     }
690 
691     // #99840#: prevent EE/Outliner notifications during setup
692     mbNotificationsDisabled = sal_False;
693 
694 	return mpTextForwarder;
695 }
696 
697 //------------------------------------------------------------------------
698 
699 SvxTextForwarder* SvxTextEditSourceImpl::GetEditModeTextForwarder()
700 {
701     if( !mpTextForwarder && HasView() )
702     {
703         SdrOutliner* pEditOutliner = mpView->GetTextEditOutliner();
704 
705         if( pEditOutliner )
706         {
707 			mpTextForwarder = new SvxOutlinerForwarder( *pEditOutliner, (mpObject->GetObjInventor() == SdrInventor) && (mpObject->GetObjIdentifier() == OBJ_OUTLINETEXT) );
708             mbForwarderIsEditMode = sal_True;
709         }
710     }
711 
712     return mpTextForwarder;
713 }
714 
715 //------------------------------------------------------------------------
716 
717 SvxTextForwarder* SvxTextEditSourceImpl::GetTextForwarder()
718 {
719 	if( mbDestroyed || mpObject == NULL )
720 		return NULL;
721 
722 	if( mpModel == NULL )
723 		mpModel = mpObject->GetModel();
724 
725 	if( mpModel == NULL )
726 		return NULL;
727 
728     // distinguish the cases
729     // a) connected to view, maybe edit mode is active, can work directly on the EditOutliner
730     // b) background Outliner, reflect changes into ParaOutlinerObject (this is exactly the old UNO code)
731     if( HasView() )
732     {
733         if( IsEditMode() != mbForwarderIsEditMode )
734         {
735             // forwarder mismatch - create new
736             delete mpTextForwarder;
737             mpTextForwarder = NULL;
738         }
739 
740         if( IsEditMode() )
741             return GetEditModeTextForwarder();
742         else
743             return GetBackgroundTextForwarder();
744     }
745     else
746         return GetBackgroundTextForwarder();
747 }
748 
749 //------------------------------------------------------------------------
750 
751 SvxDrawOutlinerViewForwarder* SvxTextEditSourceImpl::CreateViewForwarder()
752 {
753     if( mpView->GetTextEditOutlinerView() && mpObject )
754     {
755         // register as listener - need to broadcast state change messages
756         mpView->GetTextEditOutliner()->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) );
757 
758 		SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
759 		if( pTextObj )
760         {
761             Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
762             OutlinerView& rOutlView = *mpView->GetTextEditOutlinerView();
763 
764             return new SvxDrawOutlinerViewForwarder( rOutlView, aBoundRect.TopLeft() );
765         }
766     }
767 
768     return NULL;
769 }
770 
771 SvxEditViewForwarder* SvxTextEditSourceImpl::GetEditViewForwarder( sal_Bool bCreate )
772 {
773 	if( mbDestroyed || mpObject == NULL )
774 		return NULL;
775 
776 	if( mpModel == NULL )
777 		mpModel = mpObject->GetModel();
778 
779 	if( mpModel == NULL )
780 		return NULL;
781 
782     // shall we delete?
783     if( mpViewForwarder )
784     {
785         if( !IsEditMode() )
786         {
787             // destroy all forwarders (no need for UpdateData(),
788             // it's been synched on SdrEndTextEdit)
789 			delete mpViewForwarder;
790 			mpViewForwarder = NULL;
791         }
792     }
793     // which to create? Directly in edit mode, create new, or none?
794     else if( mpView )
795     {
796         if( IsEditMode() )
797         {
798             // create new view forwarder
799             mpViewForwarder = CreateViewForwarder();
800         }
801         else if( bCreate )
802         {
803             // dispose old text forwarder
804             UpdateData();
805 
806             delete mpTextForwarder;
807             mpTextForwarder = NULL;
808 
809             // enter edit mode
810             mpView->SdrEndTextEdit();
811 
812 			if(mpView->SdrBeginTextEdit(mpObject, 0L, 0L, sal_False, (SdrOutliner*)0L, 0L, sal_False, sal_False))
813             {
814                 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
815                 if( pTextObj->IsTextEditActive() )
816                 {
817                     // create new view forwarder
818                     mpViewForwarder = CreateViewForwarder();
819                 }
820                 else
821                 {
822                     // failure. Somehow, SdrBeginTextEdit did not set
823                     // our SdrTextObj into edit mode
824                     mpView->SdrEndTextEdit();
825                 }
826             }
827         }
828     }
829 
830 	return mpViewForwarder;
831 }
832 
833 //------------------------------------------------------------------------
834 
835 void SvxTextEditSourceImpl::UpdateData()
836 {
837     // if we have a view and in edit mode, we're working with the
838     // DrawOutliner. Thus, all changes made on the text forwarder are
839     // reflected on the view and committed to the model on
840     // SdrEndTextEdit(). Thus, no need for explicit updates here.
841     if( !HasView() || !IsEditMode() )
842     {
843         if( mbIsLocked  )
844         {
845             mbNeedsUpdate = sal_True;
846         }
847         else
848         {
849             if( mpOutliner && mpObject && mpText && !mbDestroyed )
850             {
851                 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
852                 if( pTextObj )
853                 {
854                     if( mpOutliner->GetParagraphCount() != 1 || mpOutliner->GetEditEngine().GetTextLen( 0 ) )
855 				    {
856 					    if( mpOutliner->GetParagraphCount() > 1 )
857 					    {
858 						    if( pTextObj && pTextObj->IsTextFrame() && pTextObj->GetTextKind() == OBJ_TITLETEXT )
859 						    {
860 							    while( mpOutliner->GetParagraphCount() > 1 )
861 							    {
862 								    ESelection aSel( 0,mpOutliner->GetEditEngine().GetTextLen( 0 ), 1,0 );
863 								    mpOutliner->QuickInsertLineBreak( aSel );
864 							    }
865 						    }
866 					    }
867 
868                         pTextObj->NbcSetOutlinerParaObjectForText( mpOutliner->CreateParaObject(), mpText );
869 				    }
870                     else
871                     {
872                         pTextObj->NbcSetOutlinerParaObjectForText( NULL,mpText );
873                     }
874                 }
875 
876                 if( mpObject->IsEmptyPresObj() )
877                     mpObject->SetEmptyPresObj(sal_False);
878             }
879         }
880     }
881 }
882 
883 void SvxTextEditSourceImpl::lock()
884 {
885 	mbIsLocked = sal_True;
886 	if( mpOutliner )
887 	{
888 		((EditEngine*)&(mpOutliner->GetEditEngine()))->SetUpdateMode( sal_False );
889 		mbOldUndoMode = ((EditEngine*)&(mpOutliner->GetEditEngine()))->IsUndoEnabled();
890 		((EditEngine*)&(mpOutliner->GetEditEngine()))->EnableUndo( sal_False );
891 	}
892 }
893 
894 void SvxTextEditSourceImpl::unlock()
895 {
896 	mbIsLocked = sal_False;
897 
898 	if( mbNeedsUpdate )
899 	{
900 		UpdateData();
901 		mbNeedsUpdate = sal_False;
902 	}
903 
904 	if( mpOutliner )
905 	{
906 		((EditEngine*)&(mpOutliner->GetEditEngine()))->SetUpdateMode( sal_True );
907 		((EditEngine*)&(mpOutliner->GetEditEngine()))->EnableUndo( mbOldUndoMode );
908 	}
909 }
910 
911 sal_Bool SvxTextEditSourceImpl::IsValid() const
912 {
913     return mpView && mpWindow ? sal_True : sal_False;
914 }
915 
916 Rectangle SvxTextEditSourceImpl::GetVisArea()
917 {
918     if( IsValid() )
919     {
920 		SdrPaintWindow* pPaintWindow = mpView->FindPaintWindow(*mpWindow);
921 		Rectangle aVisArea;
922 
923 		if(pPaintWindow)
924 		{
925 			aVisArea = pPaintWindow->GetVisibleArea();
926 		}
927 
928         // offset vis area by edit engine left-top position
929         SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
930         if( pTextObj )
931         {
932             Rectangle aAnchorRect;
933             pTextObj->TakeTextAnchorRect( aAnchorRect );
934             aVisArea.Move( -aAnchorRect.Left(), -aAnchorRect.Top() );
935 
936             MapMode aMapMode(mpWindow->GetMapMode());
937             aMapMode.SetOrigin(Point());
938             return mpWindow->LogicToPixel( aVisArea, aMapMode );
939         }
940     }
941 
942     return Rectangle();
943 }
944 
945 Point SvxTextEditSourceImpl::LogicToPixel( const Point& rPoint, const MapMode& rMapMode )
946 {
947     // #101029#: The responsibilities of ViewForwarder happen to be
948     // somewhat mixed in this case. On the one hand, we need the
949     // different interface queries on the SvxEditSource interface,
950     // since we need both VisAreas. On the other hand, if an
951     // EditViewForwarder exists, maTextOffset does not remain static,
952     // but may change with every key press.
953     if( IsEditMode() )
954     {
955         SvxEditViewForwarder* pForwarder = GetEditViewForwarder(sal_False);
956 
957         if( pForwarder )
958             return pForwarder->LogicToPixel( rPoint, rMapMode );
959     }
960     else if( IsValid() && mpModel )
961     {
962         // #101029#
963         Point aPoint1( rPoint );
964         aPoint1.X() += maTextOffset.X();
965         aPoint1.Y() += maTextOffset.Y();
966 
967         Point aPoint2( OutputDevice::LogicToLogic( aPoint1, rMapMode,
968                                                    MapMode(mpModel->GetScaleUnit()) ) );
969         MapMode aMapMode(mpWindow->GetMapMode());
970         aMapMode.SetOrigin(Point());
971         return mpWindow->LogicToPixel( aPoint2, aMapMode );
972     }
973 
974     return Point();
975 }
976 
977 Point SvxTextEditSourceImpl::PixelToLogic( const Point& rPoint, const MapMode& rMapMode )
978 {
979     // #101029#: The responsibilities of ViewForwarder happen to be
980     // somewhat mixed in this case. On the one hand, we need the
981     // different interface queries on the SvxEditSource interface,
982     // since we need both VisAreas. On the other hand, if an
983     // EditViewForwarder exists, maTextOffset does not remain static,
984     // but may change with every key press.
985     if( IsEditMode() )
986     {
987         SvxEditViewForwarder* pForwarder = GetEditViewForwarder(sal_False);
988 
989         if( pForwarder )
990             return pForwarder->PixelToLogic( rPoint, rMapMode );
991     }
992     else if( IsValid() && mpModel )
993     {
994         MapMode aMapMode(mpWindow->GetMapMode());
995         aMapMode.SetOrigin(Point());
996         Point aPoint1( mpWindow->PixelToLogic( rPoint, aMapMode ) );
997         Point aPoint2( OutputDevice::LogicToLogic( aPoint1,
998                                                    MapMode(mpModel->GetScaleUnit()),
999                                                    rMapMode ) );
1000         // #101029#
1001         aPoint2.X() -= maTextOffset.X();
1002         aPoint2.Y() -= maTextOffset.Y();
1003 
1004         return aPoint2;
1005     }
1006 
1007     return Point();
1008 }
1009 
1010 IMPL_LINK(SvxTextEditSourceImpl, NotifyHdl, EENotify*, aNotify)
1011 {
1012     if( aNotify && !mbNotificationsDisabled )
1013     {
1014         ::std::auto_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( aNotify) );
1015 
1016         if( aHint.get() )
1017             Broadcast( *aHint.get() );
1018     }
1019 
1020     return 0;
1021 }
1022 
1023 //------------------------------------------------------------------------
1024 
1025 // --------------------------------------------------------------------
1026 // SvxTextEditSource
1027 // --------------------------------------------------------------------
1028 
1029 SvxTextEditSource::SvxTextEditSource( SdrObject* pObject, SdrText* pText, XInterface* pOwner )
1030 {
1031 	mpImpl = new SvxTextEditSourceImpl( pObject, pText, pOwner );
1032 	mpImpl->acquire();
1033 }
1034 
1035 // --------------------------------------------------------------------
1036 SvxTextEditSource::SvxTextEditSource( SdrObject& rObj, SdrText* pText, SdrView& rView, const Window& rWindow )
1037 {
1038 	mpImpl = new SvxTextEditSourceImpl( rObj, pText, rView, rWindow );
1039 	mpImpl->acquire();
1040 }
1041 
1042 // --------------------------------------------------------------------
1043 
1044 SvxTextEditSource::SvxTextEditSource( SvxTextEditSourceImpl* pImpl )
1045 {
1046 	mpImpl = pImpl;
1047 	mpImpl->acquire();
1048 }
1049 
1050 //------------------------------------------------------------------------
1051 SvxTextEditSource::~SvxTextEditSource()
1052 {
1053 	OGuard aGuard( Application::GetSolarMutex() );
1054 
1055 	mpImpl->release();
1056 }
1057 
1058 //------------------------------------------------------------------------
1059 SvxEditSource* SvxTextEditSource::Clone() const
1060 {
1061 	return new SvxTextEditSource( mpImpl );
1062 }
1063 
1064 //------------------------------------------------------------------------
1065 SvxTextForwarder* SvxTextEditSource::GetTextForwarder()
1066 {
1067     return mpImpl->GetTextForwarder();
1068 }
1069 
1070 //------------------------------------------------------------------------
1071 SvxEditViewForwarder* SvxTextEditSource::GetEditViewForwarder( sal_Bool bCreate )
1072 {
1073     return mpImpl->GetEditViewForwarder( bCreate );
1074 }
1075 
1076 //------------------------------------------------------------------------
1077 SvxViewForwarder* SvxTextEditSource::GetViewForwarder()
1078 {
1079     return this;
1080 }
1081 
1082 //------------------------------------------------------------------------
1083 void SvxTextEditSource::UpdateData()
1084 {
1085     mpImpl->UpdateData();
1086 }
1087 
1088 SfxBroadcaster& SvxTextEditSource::GetBroadcaster() const
1089 {
1090     return *mpImpl;
1091 }
1092 
1093 SdrObject* SvxTextEditSource::GetSdrObject() const
1094 {
1095     return mpImpl->GetSdrObject();
1096 }
1097 
1098 void SvxTextEditSource::lock()
1099 {
1100     mpImpl->lock();
1101 }
1102 
1103 void SvxTextEditSource::unlock()
1104 {
1105     mpImpl->unlock();
1106 }
1107 
1108 sal_Bool SvxTextEditSource::IsValid() const
1109 {
1110     return mpImpl->IsValid();
1111 }
1112 
1113 Rectangle SvxTextEditSource::GetVisArea() const
1114 {
1115     return mpImpl->GetVisArea();
1116 }
1117 
1118 Point SvxTextEditSource::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
1119 {
1120     return mpImpl->LogicToPixel( rPoint, rMapMode );
1121 }
1122 
1123 Point SvxTextEditSource::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
1124 {
1125     return mpImpl->PixelToLogic( rPoint, rMapMode );
1126 }
1127 
1128 void SvxTextEditSource::addRange( SvxUnoTextRangeBase* pNewRange )
1129 {
1130 	mpImpl->addRange( pNewRange );
1131 }
1132 
1133 void SvxTextEditSource::removeRange( SvxUnoTextRangeBase* pOldRange )
1134 {
1135 	mpImpl->removeRange( pOldRange );
1136 }
1137 
1138 const SvxUnoTextRangeBaseList& SvxTextEditSource::getRanges() const
1139 {
1140 	return mpImpl->getRanges();
1141 }
1142 
1143 void SvxTextEditSource::ChangeModel( SdrModel* pNewModel )
1144 {
1145 	mpImpl->ChangeModel( pNewModel );
1146 }
1147 
1148 void SvxTextEditSource::UpdateOutliner()
1149 {
1150     mpImpl->UpdateOutliner();
1151 }
1152