xref: /trunk/main/sc/source/ui/unoobj/textuno.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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_sc.hxx"
30 
31 
32 
33 #include "scitems.hxx"
34 #include <editeng/eeitem.hxx>
35 #include <svx/svdpool.hxx>
36 #include <svx/svdobj.hxx>
37 #include <editeng/editeng.hxx>
38 #include <editeng/editobj.hxx>
39 #include <editeng/flditem.hxx>
40 #include <svx/unomid.hxx>
41 #include <editeng/unoprnms.hxx>
42 #include <editeng/unofored.hxx>
43 #include <rtl/uuid.h>
44 #include <vcl/virdev.hxx>
45 #include <com/sun/star/awt/FontSlant.hpp>
46 
47 #include <com/sun/star/beans/PropertyAttribute.hpp>
48 #include <editeng/unoipset.hxx>
49 #include "textuno.hxx"
50 #include "fielduno.hxx"
51 #include "servuno.hxx"
52 #include "editsrc.hxx"
53 #include "docsh.hxx"
54 #include "editutil.hxx"
55 #include "unoguard.hxx"
56 #include "miscuno.hxx"
57 #include "cellsuno.hxx"
58 #include "hints.hxx"
59 #include "patattr.hxx"
60 #include "cell.hxx"
61 #include "docfunc.hxx"
62 #include "scmod.hxx"
63 
64 using namespace com::sun::star;
65 
66 //------------------------------------------------------------------------
67 
68 const SvxItemPropertySet * lcl_GetHdFtPropertySet()
69 {
70     static SfxItemPropertyMapEntry aHdFtPropertyMap_Impl[] =
71     {
72         SVX_UNOEDIT_CHAR_PROPERTIES,
73         SVX_UNOEDIT_FONT_PROPERTIES,
74         SVX_UNOEDIT_PARA_PROPERTIES,
75         SVX_UNOEDIT_NUMBERING_PROPERTIE,    // for completeness of service ParagraphProperties
76         {0,0,0,0,0,0}
77     };
78     static sal_Bool bTwipsSet = sal_False;
79 
80     if (!bTwipsSet)
81     {
82         //  modify PropertyMap to include CONVERT_TWIPS flag for font height
83         //  (headers/footers are in twips)
84 
85         SfxItemPropertyMapEntry* pEntry = aHdFtPropertyMap_Impl;
86         while (pEntry->pName)
87         {
88             if ( ( pEntry->nWID == EE_CHAR_FONTHEIGHT ||
89                    pEntry->nWID == EE_CHAR_FONTHEIGHT_CJK ||
90                    pEntry->nWID == EE_CHAR_FONTHEIGHT_CTL ) &&
91                  pEntry->nMemberId == MID_FONTHEIGHT )
92             {
93                 pEntry->nMemberId |= CONVERT_TWIPS;
94             }
95 
96             ++pEntry;
97         }
98         bTwipsSet = sal_True;
99     }
100     static SvxItemPropertySet aHdFtPropertySet_Impl( aHdFtPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() );
101     return &aHdFtPropertySet_Impl;
102 }
103 
104 //------------------------------------------------------------------------
105 
106 SC_SIMPLE_SERVICE_INFO( ScHeaderFooterContentObj, "ScHeaderFooterContentObj", "com.sun.star.sheet.HeaderFooterContent" )
107 SC_SIMPLE_SERVICE_INFO( ScHeaderFooterTextObj, "ScHeaderFooterTextObj", "stardiv.one.Text.Text" )
108 
109 //------------------------------------------------------------------------
110 
111 ScHeaderFooterContentObj::ScHeaderFooterContentObj( const EditTextObject* pLeft,
112                                                     const EditTextObject* pCenter,
113                                                     const EditTextObject* pRight ) :
114     pLeftText   ( NULL ),
115     pCenterText ( NULL ),
116     pRightText  ( NULL )
117 {
118     if ( pLeft )
119         pLeftText   = pLeft->Clone();
120     if ( pCenter )
121         pCenterText = pCenter->Clone();
122     if ( pRight )
123         pRightText  = pRight->Clone();
124 }
125 
126 ScHeaderFooterContentObj::~ScHeaderFooterContentObj()
127 {
128     delete pLeftText;
129     delete pCenterText;
130     delete pRightText;
131 }
132 
133 void ScHeaderFooterContentObj::AddListener( SfxListener& rListener )
134 {
135     rListener.StartListening( aBC );
136 }
137 
138 void ScHeaderFooterContentObj::RemoveListener( SfxListener& rListener )
139 {
140     rListener.EndListening( aBC );
141 }
142 
143 void ScHeaderFooterContentObj::UpdateText( sal_uInt16 nPart, EditEngine& rSource )
144 {
145     EditTextObject* pNew = rSource.CreateTextObject();
146     switch (nPart)
147     {
148         case SC_HDFT_LEFT:
149             delete pLeftText;
150             pLeftText = pNew;
151             break;
152         case SC_HDFT_CENTER:
153             delete pCenterText;
154             pCenterText = pNew;
155             break;
156         default:                // SC_HDFT_RIGHT
157             delete pRightText;
158             pRightText = pNew;
159             break;
160     }
161 
162     aBC.Broadcast( ScHeaderFooterChangedHint( nPart ) );
163 }
164 
165 // XHeaderFooterContent
166 
167 uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getLeftText()
168                                                 throw(uno::RuntimeException)
169 {
170     ScUnoGuard aGuard;
171     return new ScHeaderFooterTextObj( *this, SC_HDFT_LEFT );
172 }
173 
174 uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getCenterText()
175                                                 throw(uno::RuntimeException)
176 {
177     ScUnoGuard aGuard;
178     return new ScHeaderFooterTextObj( *this, SC_HDFT_CENTER );
179 }
180 
181 uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getRightText()
182                                                 throw(uno::RuntimeException)
183 {
184     ScUnoGuard aGuard;
185     return new ScHeaderFooterTextObj( *this, SC_HDFT_RIGHT );
186 }
187 
188 // XUnoTunnel
189 
190 sal_Int64 SAL_CALL ScHeaderFooterContentObj::getSomething(
191                 const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
192 {
193     if ( rId.getLength() == 16 &&
194           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
195                                     rId.getConstArray(), 16 ) )
196     {
197         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
198     }
199     return 0;
200 }
201 
202 // static
203 const uno::Sequence<sal_Int8>& ScHeaderFooterContentObj::getUnoTunnelId()
204 {
205     static uno::Sequence<sal_Int8> * pSeq = 0;
206     if( !pSeq )
207     {
208         osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
209         if( !pSeq )
210         {
211             static uno::Sequence< sal_Int8 > aSeq( 16 );
212             rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
213             pSeq = &aSeq;
214         }
215     }
216     return *pSeq;
217 }
218 
219 // static
220 ScHeaderFooterContentObj* ScHeaderFooterContentObj::getImplementation(
221                                 const uno::Reference<sheet::XHeaderFooterContent> xObj )
222 {
223     ScHeaderFooterContentObj* pRet = NULL;
224     uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
225     if (xUT.is())
226         pRet = reinterpret_cast<ScHeaderFooterContentObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
227     return pRet;
228 }
229 
230 
231 //------------------------------------------------------------------------
232 
233 ScHeaderFooterTextData::ScHeaderFooterTextData( ScHeaderFooterContentObj& rContent,
234                                                     sal_uInt16 nP ) :
235     rContentObj( rContent ),
236     nPart( nP ),
237     pEditEngine( NULL ),
238     pForwarder( NULL ),
239     bDataValid( sal_False ),
240     bInUpdate( sal_False )
241 {
242     rContentObj.acquire();              // must not go away
243     rContentObj.AddListener( *this );
244 }
245 
246 ScHeaderFooterTextData::~ScHeaderFooterTextData()
247 {
248     ScUnoGuard aGuard;      //  needed for EditEngine dtor
249 
250     rContentObj.RemoveListener( *this );
251 
252     delete pForwarder;
253     delete pEditEngine;
254 
255     rContentObj.release();
256 }
257 
258 void ScHeaderFooterTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
259 {
260     if ( rHint.ISA( ScHeaderFooterChangedHint ) )
261     {
262         if ( ((const ScHeaderFooterChangedHint&)rHint).GetPart() == nPart )
263         {
264             if (!bInUpdate)             // not for own updates
265                 bDataValid = sal_False;     // text has to be fetched again
266         }
267     }
268 }
269 
270 SvxTextForwarder* ScHeaderFooterTextData::GetTextForwarder()
271 {
272     if (!pEditEngine)
273     {
274         SfxItemPool* pEnginePool = EditEngine::CreatePool();
275         pEnginePool->FreezeIdRanges();
276         ScHeaderEditEngine* pHdrEngine = new ScHeaderEditEngine( pEnginePool, sal_True );
277 
278         pHdrEngine->EnableUndo( sal_False );
279         pHdrEngine->SetRefMapMode( MAP_TWIP );
280 
281         //  default font must be set, independently of document
282         //  -> use global pool from module
283 
284         SfxItemSet aDefaults( pHdrEngine->GetEmptyItemSet() );
285         const ScPatternAttr& rPattern = (const ScPatternAttr&)SC_MOD()->GetPool().GetDefaultItem(ATTR_PATTERN);
286         rPattern.FillEditItemSet( &aDefaults );
287         //  FillEditItemSet adjusts font height to 1/100th mm,
288         //  but for header/footer twips is needed, as in the PatternAttr:
289         aDefaults.Put( rPattern.GetItem(ATTR_FONT_HEIGHT), EE_CHAR_FONTHEIGHT );
290         aDefaults.Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CJK );
291         aDefaults.Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CTL );
292         pHdrEngine->SetDefaults( aDefaults );
293 
294         ScHeaderFieldData aData;
295         ScHeaderFooterTextObj::FillDummyFieldData( aData );
296         pHdrEngine->SetData( aData );
297 
298         pEditEngine = pHdrEngine;
299         pForwarder = new SvxEditEngineForwarder(*pEditEngine);
300     }
301 
302     if (bDataValid)
303         return pForwarder;
304 
305     const EditTextObject* pData;
306     if (nPart == SC_HDFT_LEFT)
307         pData = rContentObj.GetLeftEditObject();
308     else if (nPart == SC_HDFT_CENTER)
309         pData = rContentObj.GetCenterEditObject();
310     else
311         pData = rContentObj.GetRightEditObject();
312 
313     if (pData)
314         pEditEngine->SetText(*pData);
315 
316     bDataValid = sal_True;
317     return pForwarder;
318 }
319 
320 void ScHeaderFooterTextData::UpdateData()
321 {
322     if ( pEditEngine )
323     {
324         bInUpdate = sal_True;   // don't reset bDataValid during UpdateText
325 
326         rContentObj.UpdateText( nPart, *pEditEngine );
327 
328         bInUpdate = sal_False;
329     }
330 }
331 
332 //------------------------------------------------------------------------
333 
334 ScHeaderFooterTextObj::ScHeaderFooterTextObj( ScHeaderFooterContentObj& rContent,
335                                                 sal_uInt16 nP ) :
336     aTextData( rContent, nP ),
337     pUnoText( NULL )
338 {
339     //  ScHeaderFooterTextData acquires rContent
340     //  pUnoText is created on demand (getString/setString work without it)
341 }
342 
343 void ScHeaderFooterTextObj::CreateUnoText_Impl()
344 {
345     if ( !pUnoText )
346     {
347         //  can't be aggregated because getString/setString is handled here
348         ScSharedHeaderFooterEditSource aEditSource( &aTextData );
349         pUnoText = new SvxUnoText( &aEditSource, lcl_GetHdFtPropertySet(), uno::Reference<text::XText>() );
350         pUnoText->acquire();
351     }
352 }
353 
354 ScHeaderFooterTextObj::~ScHeaderFooterTextObj()
355 {
356     if (pUnoText)
357         pUnoText->release();
358 }
359 
360 const SvxUnoText& ScHeaderFooterTextObj::GetUnoText()
361 {
362     if (!pUnoText)
363         CreateUnoText_Impl();
364     return *pUnoText;
365 }
366 
367 // XText
368 
369 uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursor()
370                                                     throw(uno::RuntimeException)
371 {
372     ScUnoGuard aGuard;
373     return new ScHeaderFooterTextCursor( *this );
374 }
375 
376 uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursorByRange(
377                                     const uno::Reference<text::XTextRange>& aTextPosition )
378                                                     throw(uno::RuntimeException)
379 {
380     ScUnoGuard aGuard;
381     if (!pUnoText)
382         CreateUnoText_Impl();
383     return pUnoText->createTextCursorByRange(aTextPosition);
384     //! wie ScCellObj::createTextCursorByRange, wenn SvxUnoTextRange_getReflection verfuegbar
385 }
386 
387 void ScHeaderFooterTextObj::FillDummyFieldData( ScHeaderFieldData& rData )  // static
388 {
389     String aDummy(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( "???" )));
390     rData.aTitle        = aDummy;
391     rData.aLongDocName  = aDummy;
392     rData.aShortDocName = aDummy;
393     rData.aTabName      = aDummy;
394     rData.nPageNo       = 1;
395     rData.nTotalPages   = 99;
396 }
397 
398 rtl::OUString SAL_CALL ScHeaderFooterTextObj::getString() throw(uno::RuntimeException)
399 {
400     ScUnoGuard aGuard;
401     rtl::OUString aRet;
402     const EditTextObject* pData;
403 
404     sal_uInt16 nPart = aTextData.GetPart();
405     ScHeaderFooterContentObj& rContentObj = aTextData.GetContentObj();
406 
407     if (nPart == SC_HDFT_LEFT)
408         pData = rContentObj.GetLeftEditObject();
409     else if (nPart == SC_HDFT_CENTER)
410         pData = rContentObj.GetCenterEditObject();
411     else
412         pData = rContentObj.GetRightEditObject();
413     if (pData)
414     {
415         // for pure text, no font info is needed in pool defaults
416         ScHeaderEditEngine aEditEngine( EditEngine::CreatePool(), sal_True );
417 
418         ScHeaderFieldData aData;
419         FillDummyFieldData( aData );
420         aEditEngine.SetData( aData );
421 
422         aEditEngine.SetText(*pData);
423         aRet = ScEditUtil::GetSpaceDelimitedString( aEditEngine );
424     }
425     return aRet;
426 }
427 
428 void SAL_CALL ScHeaderFooterTextObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException)
429 {
430     ScUnoGuard aGuard;
431     String aString(aText);
432 
433     // for pure text, no font info is needed in pool defaults
434     ScHeaderEditEngine aEditEngine( EditEngine::CreatePool(), sal_True );
435     aEditEngine.SetText( aString );
436 
437     aTextData.GetContentObj().UpdateText( aTextData.GetPart(), aEditEngine );
438 }
439 
440 void SAL_CALL ScHeaderFooterTextObj::insertString( const uno::Reference<text::XTextRange>& xRange,
441                                             const rtl::OUString& aString, sal_Bool bAbsorb )
442                                 throw(uno::RuntimeException)
443 {
444     ScUnoGuard aGuard;
445     if (!pUnoText)
446         CreateUnoText_Impl();
447     pUnoText->insertString( xRange, aString, bAbsorb );
448 }
449 
450 void SAL_CALL ScHeaderFooterTextObj::insertControlCharacter(
451                                             const uno::Reference<text::XTextRange>& xRange,
452                                             sal_Int16 nControlCharacter, sal_Bool bAbsorb )
453                                 throw(lang::IllegalArgumentException, uno::RuntimeException)
454 {
455     ScUnoGuard aGuard;
456     if (!pUnoText)
457         CreateUnoText_Impl();
458     pUnoText->insertControlCharacter( xRange, nControlCharacter, bAbsorb );
459 }
460 
461 void SAL_CALL ScHeaderFooterTextObj::insertTextContent(
462                                             const uno::Reference<text::XTextRange >& xRange,
463                                             const uno::Reference<text::XTextContent >& xContent,
464                                             sal_Bool bAbsorb )
465                                 throw(lang::IllegalArgumentException, uno::RuntimeException)
466 {
467     ScUnoGuard aGuard;
468     if ( xContent.is() && xRange.is() )
469     {
470         ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent );
471 
472         SvxUnoTextRangeBase* pTextRange =
473             ScHeaderFooterTextCursor::getImplementation( xRange );
474 
475 #if 0
476         if (!pTextRange)
477             pTextRange = (SvxUnoTextRange*)xRange->getImplementation(
478                                             SvxUnoTextRange_getReflection() );
479         //! bei SvxUnoTextRange testen, ob in passendem Objekt !!!
480 #endif
481 
482         if ( pHeaderField && !pHeaderField->IsInserted() && pTextRange )
483         {
484             SvxEditSource* pEditSource = pTextRange->GetEditSource();
485             ESelection aSelection(pTextRange->GetSelection());
486 
487             if (!bAbsorb)
488             {
489                 //  don't replace -> append at end
490                 aSelection.Adjust();
491                 aSelection.nStartPara = aSelection.nEndPara;
492                 aSelection.nStartPos  = aSelection.nEndPos;
493             }
494 
495             SvxFieldItem aItem(pHeaderField->CreateFieldItem());
496 
497             SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder();
498             pForwarder->QuickInsertField( aItem, aSelection );
499             pEditSource->UpdateData();
500 
501             //  neue Selektion: ein Zeichen
502             aSelection.Adjust();
503             aSelection.nEndPara = aSelection.nStartPara;
504             aSelection.nEndPos = aSelection.nStartPos + 1;
505             pHeaderField->InitDoc( &aTextData.GetContentObj(), aTextData.GetPart(), aSelection );
506 
507             //  #91431# for bAbsorb=sal_False, the new selection must be behind the inserted content
508             //  (the xml filter relies on this)
509             if (!bAbsorb)
510                 aSelection.nStartPos = aSelection.nEndPos;
511 
512             pTextRange->SetSelection( aSelection );
513 
514             return;
515         }
516     }
517 
518     if (!pUnoText)
519         CreateUnoText_Impl();
520     pUnoText->insertTextContent( xRange, xContent, bAbsorb );
521 }
522 
523 void SAL_CALL ScHeaderFooterTextObj::removeTextContent(
524                                             const uno::Reference<text::XTextContent>& xContent )
525                                 throw(container::NoSuchElementException, uno::RuntimeException)
526 {
527     ScUnoGuard aGuard;
528     if ( xContent.is() )
529     {
530         ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent );
531         if ( pHeaderField && pHeaderField->IsInserted() )
532         {
533             //! Testen, ob das Feld in dieser Zelle ist
534             pHeaderField->DeleteField();
535             return;
536         }
537     }
538     if (!pUnoText)
539         CreateUnoText_Impl();
540     pUnoText->removeTextContent( xContent );
541 }
542 
543 uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextObj::getText() throw(uno::RuntimeException)
544 {
545     ScUnoGuard aGuard;
546     if (!pUnoText)
547         CreateUnoText_Impl();
548     return pUnoText->getText();
549 }
550 
551 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getStart() throw(uno::RuntimeException)
552 {
553     ScUnoGuard aGuard;
554     if (!pUnoText)
555         CreateUnoText_Impl();
556     return pUnoText->getStart();
557 }
558 
559 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getEnd() throw(uno::RuntimeException)
560 {
561     ScUnoGuard aGuard;
562     if (!pUnoText)
563         CreateUnoText_Impl();
564     return pUnoText->getEnd();
565 }
566 
567 // XTextFieldsSupplier
568 
569 uno::Reference<container::XEnumerationAccess> SAL_CALL ScHeaderFooterTextObj::getTextFields()
570                                                 throw(uno::RuntimeException)
571 {
572     ScUnoGuard aGuard;
573     // all fields
574     return new ScHeaderFieldsObj( &aTextData.GetContentObj(), aTextData.GetPart(), SC_SERVICE_INVALID );
575 }
576 
577 uno::Reference<container::XNameAccess> SAL_CALL ScHeaderFooterTextObj::getTextFieldMasters()
578                                                 throw(uno::RuntimeException)
579 {
580     //  sowas gibts nicht im Calc (?)
581     return NULL;
582 }
583 
584 // XTextRangeMover
585 
586 void SAL_CALL ScHeaderFooterTextObj::moveTextRange(
587                                         const uno::Reference<text::XTextRange>& xRange,
588                                         sal_Int16 nParagraphs )
589                                         throw(uno::RuntimeException)
590 {
591     ScUnoGuard aGuard;
592     if (!pUnoText)
593         CreateUnoText_Impl();
594     pUnoText->moveTextRange( xRange, nParagraphs );
595 }
596 
597 // XEnumerationAccess
598 
599 uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFooterTextObj::createEnumeration()
600                                                 throw(uno::RuntimeException)
601 {
602     ScUnoGuard aGuard;
603     if (!pUnoText)
604         CreateUnoText_Impl();
605     return pUnoText->createEnumeration();
606 }
607 
608 // XElementAccess
609 
610 uno::Type SAL_CALL ScHeaderFooterTextObj::getElementType() throw(uno::RuntimeException)
611 {
612     ScUnoGuard aGuard;
613     if (!pUnoText)
614         CreateUnoText_Impl();
615     return pUnoText->getElementType();
616 }
617 
618 sal_Bool SAL_CALL ScHeaderFooterTextObj::hasElements() throw(uno::RuntimeException)
619 {
620     ScUnoGuard aGuard;
621     if (!pUnoText)
622         CreateUnoText_Impl();
623     return pUnoText->hasElements();
624 }
625 
626 //------------------------------------------------------------------------
627 
628 ScCellTextCursor::ScCellTextCursor(const ScCellTextCursor& rOther) :
629     SvxUnoTextCursor( rOther ),
630     rTextObj( rOther.rTextObj )
631 {
632     rTextObj.acquire();
633 }
634 
635 ScCellTextCursor::ScCellTextCursor(ScCellObj& rText) :
636     SvxUnoTextCursor( rText.GetUnoText() ),
637     rTextObj( rText )
638 {
639     rTextObj.acquire();
640 }
641 
642 ScCellTextCursor::~ScCellTextCursor() throw()
643 {
644     rTextObj.release();
645 }
646 
647 // SvxUnoTextCursor methods reimplemented here to return the right objects:
648 
649 uno::Reference<text::XText> SAL_CALL ScCellTextCursor::getText() throw(uno::RuntimeException)
650 {
651     ScUnoGuard aGuard;
652     return &rTextObj;
653 }
654 
655 uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getStart() throw(uno::RuntimeException)
656 {
657     ScUnoGuard aGuard;
658 
659     //! use other object for range than cursor?
660 
661     ScCellTextCursor* pNew = new ScCellTextCursor( *this );
662     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
663 
664     ESelection aNewSel(GetSelection());
665     aNewSel.nEndPara = aNewSel.nStartPara;
666     aNewSel.nEndPos  = aNewSel.nStartPos;
667     pNew->SetSelection( aNewSel );
668 
669     return xRange;
670 }
671 
672 uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getEnd() throw(uno::RuntimeException)
673 {
674     ScUnoGuard aGuard;
675 
676     //! use other object for range than cursor?
677 
678     ScCellTextCursor* pNew = new ScCellTextCursor( *this );
679     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
680 
681     ESelection aNewSel(GetSelection());
682     aNewSel.nStartPara = aNewSel.nEndPara;
683     aNewSel.nStartPos  = aNewSel.nEndPos;
684     pNew->SetSelection( aNewSel );
685 
686     return xRange;
687 }
688 
689 // XUnoTunnel
690 
691 sal_Int64 SAL_CALL ScCellTextCursor::getSomething(
692                 const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
693 {
694     if ( rId.getLength() == 16 &&
695           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
696                                     rId.getConstArray(), 16 ) )
697     {
698         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
699     }
700     return SvxUnoTextCursor::getSomething( rId );
701 }
702 
703 // static
704 const uno::Sequence<sal_Int8>& ScCellTextCursor::getUnoTunnelId()
705 {
706     static uno::Sequence<sal_Int8> * pSeq = 0;
707     if( !pSeq )
708     {
709         osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
710         if( !pSeq )
711         {
712             static uno::Sequence< sal_Int8 > aSeq( 16 );
713             rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
714             pSeq = &aSeq;
715         }
716     }
717     return *pSeq;
718 }
719 
720 // static
721 ScCellTextCursor* ScCellTextCursor::getImplementation( const uno::Reference<uno::XInterface> xObj )
722 {
723     ScCellTextCursor* pRet = NULL;
724     uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
725     if (xUT.is())
726         pRet = reinterpret_cast<ScCellTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
727     return pRet;
728 }
729 
730 //------------------------------------------------------------------------
731 
732 ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(const ScHeaderFooterTextCursor& rOther) :
733     SvxUnoTextCursor( rOther ),
734     rTextObj( rOther.rTextObj )
735 {
736     rTextObj.acquire();
737 }
738 
739 ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(ScHeaderFooterTextObj& rText) :
740     SvxUnoTextCursor( rText.GetUnoText() ),
741     rTextObj( rText )
742 {
743     rTextObj.acquire();
744 }
745 
746 ScHeaderFooterTextCursor::~ScHeaderFooterTextCursor() throw()
747 {
748     rTextObj.release();
749 }
750 
751 // SvxUnoTextCursor methods reimplemented here to return the right objects:
752 
753 uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextCursor::getText() throw(uno::RuntimeException)
754 {
755     ScUnoGuard aGuard;
756     return &rTextObj;
757 }
758 
759 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getStart() throw(uno::RuntimeException)
760 {
761     ScUnoGuard aGuard;
762 
763     //! use other object for range than cursor?
764 
765     ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this );
766     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
767 
768     ESelection aNewSel(GetSelection());
769     aNewSel.nEndPara = aNewSel.nStartPara;
770     aNewSel.nEndPos  = aNewSel.nStartPos;
771     pNew->SetSelection( aNewSel );
772 
773     return xRange;
774 }
775 
776 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getEnd() throw(uno::RuntimeException)
777 {
778     ScUnoGuard aGuard;
779 
780     //! use other object for range than cursor?
781 
782     ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this );
783     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
784 
785     ESelection aNewSel(GetSelection());
786     aNewSel.nStartPara = aNewSel.nEndPara;
787     aNewSel.nStartPos  = aNewSel.nEndPos;
788     pNew->SetSelection( aNewSel );
789 
790     return xRange;
791 }
792 
793 // XUnoTunnel
794 
795 sal_Int64 SAL_CALL ScHeaderFooterTextCursor::getSomething(
796                 const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
797 {
798     if ( rId.getLength() == 16 &&
799           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
800                                     rId.getConstArray(), 16 ) )
801     {
802         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
803     }
804     return SvxUnoTextCursor::getSomething( rId );
805 }
806 
807 // static
808 const uno::Sequence<sal_Int8>& ScHeaderFooterTextCursor::getUnoTunnelId()
809 {
810     static uno::Sequence<sal_Int8> * pSeq = 0;
811     if( !pSeq )
812     {
813         osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
814         if( !pSeq )
815         {
816             static uno::Sequence< sal_Int8 > aSeq( 16 );
817             rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
818             pSeq = &aSeq;
819         }
820     }
821     return *pSeq;
822 }
823 
824 // static
825 ScHeaderFooterTextCursor* ScHeaderFooterTextCursor::getImplementation(
826                                 const uno::Reference<uno::XInterface> xObj )
827 {
828     ScHeaderFooterTextCursor* pRet = NULL;
829     uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
830     if (xUT.is())
831         pRet = reinterpret_cast<ScHeaderFooterTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
832     return pRet;
833 }
834 
835 //------------------------------------------------------------------------
836 
837 ScDrawTextCursor::ScDrawTextCursor(const ScDrawTextCursor& rOther) :
838     SvxUnoTextCursor( rOther ),
839     xParentText( rOther.xParentText )
840 {
841 }
842 
843 ScDrawTextCursor::ScDrawTextCursor( const uno::Reference<text::XText>& xParent,
844                                     const SvxUnoTextBase& rText ) :
845     SvxUnoTextCursor( rText ),
846     xParentText( xParent )
847 
848 {
849 }
850 
851 ScDrawTextCursor::~ScDrawTextCursor() throw()
852 {
853 }
854 
855 // SvxUnoTextCursor methods reimplemented here to return the right objects:
856 
857 uno::Reference<text::XText> SAL_CALL ScDrawTextCursor::getText() throw(uno::RuntimeException)
858 {
859     ScUnoGuard aGuard;
860     return xParentText;
861 }
862 
863 uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getStart() throw(uno::RuntimeException)
864 {
865     ScUnoGuard aGuard;
866 
867     //! use other object for range than cursor?
868 
869     ScDrawTextCursor* pNew = new ScDrawTextCursor( *this );
870     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
871 
872     ESelection aNewSel(GetSelection());
873     aNewSel.nEndPara = aNewSel.nStartPara;
874     aNewSel.nEndPos  = aNewSel.nStartPos;
875     pNew->SetSelection( aNewSel );
876 
877     return xRange;
878 }
879 
880 uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getEnd() throw(uno::RuntimeException)
881 {
882     ScUnoGuard aGuard;
883 
884     //! use other object for range than cursor?
885 
886     ScDrawTextCursor* pNew = new ScDrawTextCursor( *this );
887     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
888 
889     ESelection aNewSel(GetSelection());
890     aNewSel.nStartPara = aNewSel.nEndPara;
891     aNewSel.nStartPos  = aNewSel.nEndPos;
892     pNew->SetSelection( aNewSel );
893 
894     return xRange;
895 }
896 
897 // XUnoTunnel
898 
899 sal_Int64 SAL_CALL ScDrawTextCursor::getSomething(
900                 const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
901 {
902     if ( rId.getLength() == 16 &&
903           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
904                                     rId.getConstArray(), 16 ) )
905     {
906         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
907     }
908     return SvxUnoTextCursor::getSomething( rId );
909 }
910 
911 // static
912 const uno::Sequence<sal_Int8>& ScDrawTextCursor::getUnoTunnelId()
913 {
914     static uno::Sequence<sal_Int8> * pSeq = 0;
915     if( !pSeq )
916     {
917         osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
918         if( !pSeq )
919         {
920             static uno::Sequence< sal_Int8 > aSeq( 16 );
921             rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
922             pSeq = &aSeq;
923         }
924     }
925     return *pSeq;
926 }
927 
928 // static
929 ScDrawTextCursor* ScDrawTextCursor::getImplementation( const uno::Reference<uno::XInterface> xObj )
930 {
931     ScDrawTextCursor* pRet = NULL;
932     uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
933     if (xUT.is())
934         pRet = reinterpret_cast<ScDrawTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
935     return pRet;
936 }
937 
938 //------------------------------------------------------------------------
939 
940 ScSimpleEditSourceHelper::ScSimpleEditSourceHelper()
941 {
942     SfxItemPool* pEnginePool = EditEngine::CreatePool();
943     pEnginePool->SetDefaultMetric( SFX_MAPUNIT_100TH_MM );
944     pEnginePool->FreezeIdRanges();
945 
946     pEditEngine = new ScFieldEditEngine( pEnginePool, NULL, sal_True );     // TRUE: become owner of pool
947     pForwarder = new SvxEditEngineForwarder( *pEditEngine );
948     pOriginalSource = new ScSimpleEditSource( pForwarder );
949 }
950 
951 ScSimpleEditSourceHelper::~ScSimpleEditSourceHelper()
952 {
953     ScUnoGuard aGuard;      //  needed for EditEngine dtor
954 
955     delete pOriginalSource;
956     delete pForwarder;
957     delete pEditEngine;
958 }
959 
960 ScEditEngineTextObj::ScEditEngineTextObj() :
961     SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() )
962 {
963 }
964 
965 ScEditEngineTextObj::~ScEditEngineTextObj() throw()
966 {
967 }
968 
969 void ScEditEngineTextObj::SetText( const EditTextObject& rTextObject )
970 {
971     GetEditEngine()->SetText( rTextObject );
972 
973     ESelection aSel;
974     ::GetSelection( aSel, GetEditSource()->GetTextForwarder() );
975     SetSelection( aSel );
976 }
977 
978 EditTextObject* ScEditEngineTextObj::CreateTextObject()
979 {
980     return GetEditEngine()->CreateTextObject();
981 }
982 
983 //------------------------------------------------------------------------
984 
985 ScCellTextData::ScCellTextData(ScDocShell* pDocSh, const ScAddress& rP) :
986     pDocShell( pDocSh ),
987     aCellPos( rP ),
988     pEditEngine( NULL ),
989     pForwarder( NULL ),
990     pOriginalSource( NULL ),
991     bDataValid( sal_False ),
992     bInUpdate( sal_False ),
993     bDirty( sal_False ),
994     bDoUpdate( sal_True )
995 {
996     if (pDocShell)
997         pDocShell->GetDocument()->AddUnoObject(*this);
998 }
999 
1000 ScCellTextData::~ScCellTextData()
1001 {
1002     ScUnoGuard aGuard;      //  needed for EditEngine dtor
1003 
1004     if (pDocShell)
1005     {
1006         pDocShell->GetDocument()->RemoveUnoObject(*this);
1007         pDocShell->GetDocument()->DisposeFieldEditEngine(pEditEngine);
1008     }
1009     else
1010         delete pEditEngine;
1011 
1012     delete pForwarder;
1013 
1014     delete pOriginalSource;
1015 }
1016 
1017 ScSharedCellEditSource* ScCellTextData::GetOriginalSource()
1018 {
1019     if (!pOriginalSource)
1020         pOriginalSource = new ScSharedCellEditSource( this );
1021     return pOriginalSource;
1022 }
1023 
1024 void ScCellTextData::GetCellText(const ScAddress& rCellPos, String& rText)
1025 {
1026     if (pDocShell)
1027     {
1028         ScDocument* pDoc = pDocShell->GetDocument();
1029         pDoc->GetInputString( rCellPos.Col(), rCellPos.Row(), rCellPos.Tab(), rText );
1030     }
1031 }
1032 
1033 SvxTextForwarder* ScCellTextData::GetTextForwarder()
1034 {
1035     if (!pEditEngine)
1036     {
1037         if ( pDocShell )
1038         {
1039             ScDocument* pDoc = pDocShell->GetDocument();
1040             pEditEngine = pDoc->CreateFieldEditEngine();
1041         }
1042         else
1043         {
1044             SfxItemPool* pEnginePool = EditEngine::CreatePool();
1045             pEnginePool->FreezeIdRanges();
1046             pEditEngine = new ScFieldEditEngine( pEnginePool, NULL, sal_True );
1047         }
1048         //  currently, GetPortions doesn't work if UpdateMode is sal_False,
1049         //  this will be fixed (in EditEngine) by src600
1050 //      pEditEngine->SetUpdateMode( sal_False );
1051         pEditEngine->EnableUndo( sal_False );
1052         if (pDocShell)
1053             pEditEngine->SetRefDevice(pDocShell->GetRefDevice());
1054         else
1055             pEditEngine->SetRefMapMode( MAP_100TH_MM );
1056         pForwarder = new SvxEditEngineForwarder(*pEditEngine);
1057     }
1058 
1059     if (bDataValid)
1060         return pForwarder;
1061 
1062     String aText;
1063 
1064     if (pDocShell)
1065     {
1066         ScDocument* pDoc = pDocShell->GetDocument();
1067 
1068         SfxItemSet aDefaults( pEditEngine->GetEmptyItemSet() );
1069         if( const ScPatternAttr* pPattern =
1070                 pDoc->GetPattern( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) )
1071         {
1072             pPattern->FillEditItemSet( &aDefaults );
1073             pPattern->FillEditParaItems( &aDefaults );  // including alignment etc. (for reading)
1074         }
1075 
1076         const ScBaseCell* pCell = pDoc->GetCell( aCellPos );
1077         if ( pCell && pCell->GetCellType() == CELLTYPE_EDIT )
1078             pEditEngine->SetTextNewDefaults( *((const ScEditCell*)pCell)->GetData(), aDefaults );
1079         else
1080         {
1081             GetCellText( aCellPos, aText );
1082             if (aText.Len())
1083                 pEditEngine->SetTextNewDefaults( aText, aDefaults );
1084             else
1085                 pEditEngine->SetDefaults(aDefaults);
1086         }
1087     }
1088 
1089     bDataValid = sal_True;
1090     return pForwarder;
1091 }
1092 
1093 void ScCellTextData::UpdateData()
1094 {
1095     if ( bDoUpdate )
1096     {
1097         DBG_ASSERT(pEditEngine != NULL, "no EditEngine for UpdateData()");
1098         if ( pDocShell && pEditEngine )
1099         {
1100             //  during the own UpdateData call, bDataValid must not be reset,
1101             //  or things like attributes after the text would be lost
1102             //  (are not stored in the cell)
1103 
1104             bInUpdate = sal_True;   // prevents bDataValid from being reset
1105 
1106             ScDocFunc aFunc(*pDocShell);
1107             aFunc.PutData( aCellPos, *pEditEngine, sal_False, sal_True );   // always as text
1108 
1109             bInUpdate = sal_False;
1110             bDirty = sal_False;
1111         }
1112     }
1113     else
1114         bDirty = sal_True;
1115 }
1116 
1117 void ScCellTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
1118 {
1119     if ( rHint.ISA( ScUpdateRefHint ) )
1120     {
1121 //        const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint;
1122 
1123         //! Ref-Update
1124     }
1125     else if ( rHint.ISA( SfxSimpleHint ) )
1126     {
1127         sal_uLong nId = ((const SfxSimpleHint&)rHint).GetId();
1128         if ( nId == SFX_HINT_DYING )
1129         {
1130             pDocShell = NULL;                       // invalid now
1131 
1132             DELETEZ( pForwarder );
1133             DELETEZ( pEditEngine );     // EditEngine uses document's pool
1134         }
1135         else if ( nId == SFX_HINT_DATACHANGED )
1136         {
1137             if (!bInUpdate)                         // not for own UpdateData calls
1138                 bDataValid = sal_False;                 // text has to be read from the cell again
1139         }
1140     }
1141 }
1142 
1143 ScCellTextObj::ScCellTextObj(ScDocShell* pDocSh, const ScAddress& rP) :
1144     ScCellTextData( pDocSh, rP ),
1145     SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() )
1146 {
1147 }
1148 
1149 ScCellTextObj::~ScCellTextObj() throw()
1150 {
1151 }
1152 
1153