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