xref: /AOO41X/main/svx/source/unodraw/unoshtxt.cxx (revision ff0525f24f03981d56b7579b645949f111420994)
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