1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <sal/config.h>
22 #include <sal/log.hxx>
23 
24 #include <scitems.hxx>
25 #include <editeng/eeitem.hxx>
26 #include <svx/svdpool.hxx>
27 #include <svx/svdobj.hxx>
28 #include <editeng/editeng.hxx>
29 #include <editeng/editobj.hxx>
30 #include <editeng/flditem.hxx>
31 #include <editeng/fhgtitem.hxx>
32 #include <editeng/unoprnms.hxx>
33 #include <editeng/unofored.hxx>
34 #include <vcl/svapp.hxx>
35 
36 #include <editeng/unoipset.hxx>
37 #include <textuno.hxx>
38 #include <fielduno.hxx>
39 #include <editsrc.hxx>
40 #include <docsh.hxx>
41 #include <editutil.hxx>
42 #include <miscuno.hxx>
43 #include <cellsuno.hxx>
44 #include <cellvalue.hxx>
45 #include <cellform.hxx>
46 #include <patattr.hxx>
47 #include <docfunc.hxx>
48 #include <scmod.hxx>
49 
50 using namespace com::sun::star;
51 
lcl_GetHdFtPropertySet()52 static const SvxItemPropertySet * lcl_GetHdFtPropertySet()
53 {
54     static SfxItemPropertyMapEntry aHdFtPropertyMap_Impl[] =
55     {
56         SVX_UNOEDIT_CHAR_PROPERTIES,
57         SVX_UNOEDIT_FONT_PROPERTIES,
58         SVX_UNOEDIT_PARA_PROPERTIES,
59         SVX_UNOEDIT_NUMBERING_PROPERTIE,    // for completeness of service ParagraphProperties
60         { OUString(), 0, css::uno::Type(), 0, 0 }
61     };
62     static bool bTwipsSet = false;
63 
64     if (!bTwipsSet)
65     {
66         //  modify PropertyMap to include CONVERT_TWIPS flag for font height
67         //  (headers/footers are in twips)
68 
69         SfxItemPropertyMapEntry* pEntry = aHdFtPropertyMap_Impl;
70         while (!pEntry->aName.isEmpty())
71         {
72             if ( ( pEntry->nWID == EE_CHAR_FONTHEIGHT ||
73                    pEntry->nWID == EE_CHAR_FONTHEIGHT_CJK ||
74                    pEntry->nWID == EE_CHAR_FONTHEIGHT_CTL ) &&
75                  pEntry->nMemberId == MID_FONTHEIGHT )
76             {
77                 pEntry->nMemberId |= CONVERT_TWIPS;
78             }
79 
80             ++pEntry;
81         }
82         bTwipsSet = true;
83     }
84     static SvxItemPropertySet aHdFtPropertySet_Impl( aHdFtPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() );
85     return &aHdFtPropertySet_Impl;
86 }
87 
88 SC_SIMPLE_SERVICE_INFO( ScHeaderFooterContentObj, "ScHeaderFooterContentObj", "com.sun.star.sheet.HeaderFooterContent" )
89 SC_SIMPLE_SERVICE_INFO( ScHeaderFooterTextObj, "ScHeaderFooterTextObj", "stardiv.one.Text.Text" )
90 
ScHeaderFooterContentObj()91 ScHeaderFooterContentObj::ScHeaderFooterContentObj()
92 {
93 }
94 
~ScHeaderFooterContentObj()95 ScHeaderFooterContentObj::~ScHeaderFooterContentObj() {}
96 
GetLeftEditObject() const97 const EditTextObject* ScHeaderFooterContentObj::GetLeftEditObject() const
98 {
99     return mxLeftText->GetTextObject();
100 }
101 
GetCenterEditObject() const102 const EditTextObject* ScHeaderFooterContentObj::GetCenterEditObject() const
103 {
104     return mxCenterText->GetTextObject();
105 }
106 
GetRightEditObject() const107 const EditTextObject* ScHeaderFooterContentObj::GetRightEditObject() const
108 {
109     return mxRightText->GetTextObject();
110 }
111 
112 // XHeaderFooterContent
113 
getLeftText()114 uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getLeftText()
115 {
116     SolarMutexGuard aGuard;
117     uno::Reference<text::XText> xInt(*mxLeftText, uno::UNO_QUERY);
118     return xInt;
119 }
120 
getCenterText()121 uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getCenterText()
122 {
123     SolarMutexGuard aGuard;
124     uno::Reference<text::XText> xInt(*mxCenterText, uno::UNO_QUERY);
125     return xInt;
126 }
127 
getRightText()128 uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getRightText()
129 {
130     SolarMutexGuard aGuard;
131     uno::Reference<text::XText> xInt(*mxRightText, uno::UNO_QUERY);
132     return xInt;
133 }
134 
135 // XUnoTunnel
136 
getSomething(const uno::Sequence<sal_Int8> & rId)137 sal_Int64 SAL_CALL ScHeaderFooterContentObj::getSomething(
138                 const uno::Sequence<sal_Int8 >& rId )
139 {
140     if ( isUnoTunnelId<ScHeaderFooterContentObj>(rId) )
141     {
142         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
143     }
144     return 0;
145 }
146 
147 namespace
148 {
149     class theScHeaderFooterContentObjUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theScHeaderFooterContentObjUnoTunnelId> {};
150 }
151 
getUnoTunnelId()152 const uno::Sequence<sal_Int8>& ScHeaderFooterContentObj::getUnoTunnelId()
153 {
154     return theScHeaderFooterContentObjUnoTunnelId::get().getSeq();
155 }
156 
getImplementation(const uno::Reference<sheet::XHeaderFooterContent> & rObj)157 rtl::Reference<ScHeaderFooterContentObj> ScHeaderFooterContentObj::getImplementation(
158                                 const uno::Reference<sheet::XHeaderFooterContent>& rObj)
159 {
160     return comphelper::getUnoTunnelImplementation<ScHeaderFooterContentObj>(rObj);
161 }
162 
Init(const EditTextObject * pLeft,const EditTextObject * pCenter,const EditTextObject * pRight)163 void ScHeaderFooterContentObj::Init( const EditTextObject* pLeft,
164                                                     const EditTextObject* pCenter,
165                                                     const EditTextObject* pRight )
166 {
167     uno::Reference<css::sheet::XHeaderFooterContent> xThis(this);
168     mxLeftText = rtl::Reference<ScHeaderFooterTextObj>(new ScHeaderFooterTextObj(xThis, ScHeaderFooterPart::LEFT, pLeft));
169     mxCenterText = rtl::Reference<ScHeaderFooterTextObj>(new ScHeaderFooterTextObj(xThis, ScHeaderFooterPart::CENTER, pCenter));
170     mxRightText = rtl::Reference<ScHeaderFooterTextObj>(new ScHeaderFooterTextObj(xThis, ScHeaderFooterPart::RIGHT, pRight));
171 }
172 
ScHeaderFooterTextData(uno::WeakReference<sheet::XHeaderFooterContent> const & xContent,ScHeaderFooterPart nP,const EditTextObject * pTextObj)173 ScHeaderFooterTextData::ScHeaderFooterTextData(
174     uno::WeakReference<sheet::XHeaderFooterContent> const & xContent, ScHeaderFooterPart nP, const EditTextObject* pTextObj) :
175     mpTextObj(pTextObj ? pTextObj->Clone() : nullptr),
176     xContentObj( xContent ),
177     nPart( nP ),
178     bDataValid(false)
179 {
180 }
181 
~ScHeaderFooterTextData()182 ScHeaderFooterTextData::~ScHeaderFooterTextData()
183 {
184     SolarMutexGuard aGuard;     //  needed for EditEngine dtor
185 
186     pForwarder.reset();
187     pEditEngine.reset();
188 }
189 
GetTextForwarder()190 SvxTextForwarder* ScHeaderFooterTextData::GetTextForwarder()
191 {
192     if (!pEditEngine)
193     {
194         SfxItemPool* pEnginePool = EditEngine::CreatePool();
195         pEnginePool->FreezeIdRanges();
196         std::unique_ptr<ScHeaderEditEngine> pHdrEngine(new ScHeaderEditEngine( pEnginePool ));
197 
198         pHdrEngine->EnableUndo( false );
199         pHdrEngine->SetRefMapMode(MapMode(MapUnit::MapTwip));
200 
201         //  default font must be set, independently of document
202         //  -> use global pool from module
203 
204         SfxItemSet aDefaults( pHdrEngine->GetEmptyItemSet() );
205         const ScPatternAttr& rPattern = SC_MOD()->GetPool().GetDefaultItem(ATTR_PATTERN);
206         rPattern.FillEditItemSet( &aDefaults );
207         //  FillEditItemSet adjusts font height to 1/100th mm,
208         //  but for header/footer twips is needed, as in the PatternAttr:
209         aDefaults.Put( rPattern.GetItem(ATTR_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT) );
210         aDefaults.Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK) ) ;
211         aDefaults.Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL) );
212         pHdrEngine->SetDefaults( aDefaults );
213 
214         ScHeaderFieldData aData;
215         ScHeaderFooterTextObj::FillDummyFieldData( aData );
216         pHdrEngine->SetData( aData );
217 
218         pEditEngine = std::move(pHdrEngine);
219         pForwarder.reset( new SvxEditEngineForwarder(*pEditEngine) );
220     }
221 
222     if (bDataValid)
223         return pForwarder.get();
224 
225     if (mpTextObj)
226         pEditEngine->SetText(*mpTextObj);
227 
228     bDataValid = true;
229     return pForwarder.get();
230 }
231 
UpdateData()232 void ScHeaderFooterTextData::UpdateData()
233 {
234     if (pEditEngine)
235     {
236         mpTextObj = pEditEngine->CreateTextObject();
237     }
238 }
239 
UpdateData(EditEngine & rEditEngine)240 void ScHeaderFooterTextData::UpdateData(EditEngine& rEditEngine)
241 {
242     mpTextObj = rEditEngine.CreateTextObject();
243     bDataValid = false;
244 }
245 
ScHeaderFooterTextObj(const uno::WeakReference<sheet::XHeaderFooterContent> & xContent,ScHeaderFooterPart nP,const EditTextObject * pTextObj)246 ScHeaderFooterTextObj::ScHeaderFooterTextObj(
247     const uno::WeakReference<sheet::XHeaderFooterContent>& xContent, ScHeaderFooterPart nP, const EditTextObject* pTextObj) :
248     aTextData(xContent, nP, pTextObj)
249 {
250     //  ScHeaderFooterTextData acquires rContent
251     //  pUnoText is created on demand (getString/setString work without it)
252 }
253 
CreateUnoText_Impl()254 void ScHeaderFooterTextObj::CreateUnoText_Impl()
255 {
256     if (!mxUnoText.is())
257     {
258         //  can't be aggregated because getString/setString is handled here
259         ScHeaderFooterEditSource aEditSrc(aTextData);
260         mxUnoText.set(new SvxUnoText(&aEditSrc, lcl_GetHdFtPropertySet(), uno::Reference<text::XText>()));
261     }
262 }
263 
~ScHeaderFooterTextObj()264 ScHeaderFooterTextObj::~ScHeaderFooterTextObj() {}
265 
GetTextObject() const266 const EditTextObject* ScHeaderFooterTextObj::GetTextObject() const
267 {
268     return aTextData.GetTextObject();
269 }
270 
GetUnoText()271 const SvxUnoText& ScHeaderFooterTextObj::GetUnoText()
272 {
273     if (!mxUnoText.is())
274         CreateUnoText_Impl();
275     return *mxUnoText;
276 }
277 
278 // XText
279 
createTextCursor()280 uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursor()
281 {
282     SolarMutexGuard aGuard;
283     return new ScHeaderFooterTextCursor( this );
284 }
285 
createTextCursorByRange(const uno::Reference<text::XTextRange> & aTextPosition)286 uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursorByRange(
287                                     const uno::Reference<text::XTextRange>& aTextPosition )
288 {
289     SolarMutexGuard aGuard;
290     if (!mxUnoText.is())
291         CreateUnoText_Impl();
292     return mxUnoText->createTextCursorByRange(aTextPosition);
293     //! like ScCellObj::createTextCursorByRange, if SvxUnoTextRange_getReflection available
294 }
295 
FillDummyFieldData(ScHeaderFieldData & rData)296 void ScHeaderFooterTextObj::FillDummyFieldData( ScHeaderFieldData& rData )
297 {
298     OUString aDummy("???");
299     rData.aTitle        = aDummy;
300     rData.aLongDocName  = aDummy;
301     rData.aShortDocName = aDummy;
302     rData.aTabName      = aDummy;
303     rData.nPageNo       = 1;
304     rData.nTotalPages   = 99;
305 }
306 
getString()307 OUString SAL_CALL ScHeaderFooterTextObj::getString()
308 {
309     SolarMutexGuard aGuard;
310     OUString aRet;
311     const EditTextObject* pData;
312 
313     uno::Reference<css::sheet::XHeaderFooterContent> xContentObj = aTextData.GetContentObj();
314     if (!xContentObj.is())
315         throw css::uno::RuntimeException(
316             "ScHeaderFooterTextObj::getString: no ContentObj");
317 
318     rtl::Reference<ScHeaderFooterContentObj> pObj = ScHeaderFooterContentObj::getImplementation(xContentObj);
319 
320     switch ( aTextData.GetPart() )
321     {
322         case ScHeaderFooterPart::LEFT:
323             pData = pObj->GetLeftEditObject();
324         break;
325         case ScHeaderFooterPart::CENTER:
326             pData = pObj->GetCenterEditObject();
327         break;
328         case ScHeaderFooterPart::RIGHT:
329             pData = pObj->GetRightEditObject();
330         break;
331         default:
332             SAL_WARN("sc.ui","unexpected enum value of ScHeaderFooterPart");
333             pData = nullptr;
334     }
335 
336     if (pData)
337     {
338         // for pure text, no font info is needed in pool defaults
339         ScHeaderEditEngine aEditEngine( EditEngine::CreatePool() );
340 
341         ScHeaderFieldData aData;
342         FillDummyFieldData( aData );
343         aEditEngine.SetData( aData );
344 
345         aEditEngine.SetText(*pData);
346         aRet = ScEditUtil::GetSpaceDelimitedString( aEditEngine );
347     }
348     return aRet;
349 }
350 
setString(const OUString & aText)351 void SAL_CALL ScHeaderFooterTextObj::setString( const OUString& aText )
352 {
353     SolarMutexGuard aGuard;
354 
355     // for pure text, no font info is needed in pool defaults
356     ScHeaderEditEngine aEditEngine(EditEngine::CreatePool());
357     aEditEngine.SetText( aText );
358     aTextData.UpdateData(aEditEngine);
359 }
360 
insertString(const uno::Reference<text::XTextRange> & xRange,const OUString & aString,sal_Bool bAbsorb)361 void SAL_CALL ScHeaderFooterTextObj::insertString( const uno::Reference<text::XTextRange>& xRange,
362                                             const OUString& aString, sal_Bool bAbsorb )
363 {
364     SolarMutexGuard aGuard;
365     if (!mxUnoText.is())
366         CreateUnoText_Impl();
367     mxUnoText->insertString( xRange, aString, bAbsorb );
368 }
369 
insertControlCharacter(const uno::Reference<text::XTextRange> & xRange,sal_Int16 nControlCharacter,sal_Bool bAbsorb)370 void SAL_CALL ScHeaderFooterTextObj::insertControlCharacter(
371                                             const uno::Reference<text::XTextRange>& xRange,
372                                             sal_Int16 nControlCharacter, sal_Bool bAbsorb )
373 {
374     SolarMutexGuard aGuard;
375     if (!mxUnoText.is())
376         CreateUnoText_Impl();
377     mxUnoText->insertControlCharacter( xRange, nControlCharacter, bAbsorb );
378 }
379 
insertTextContent(const uno::Reference<text::XTextRange> & xRange,const uno::Reference<text::XTextContent> & xContent,sal_Bool bAbsorb)380 void SAL_CALL ScHeaderFooterTextObj::insertTextContent(
381                                             const uno::Reference<text::XTextRange >& xRange,
382                                             const uno::Reference<text::XTextContent >& xContent,
383                                             sal_Bool bAbsorb )
384 {
385     SolarMutexGuard aGuard;
386     if ( xContent.is() && xRange.is() )
387     {
388         ScEditFieldObj* pHeaderField = comphelper::getUnoTunnelImplementation<ScEditFieldObj>( xContent );
389 
390         SvxUnoTextRangeBase* pTextRange =
391             comphelper::getUnoTunnelImplementation<ScHeaderFooterTextCursor>( xRange );
392 
393         if ( pHeaderField && !pHeaderField->IsInserted() && pTextRange )
394         {
395             SvxEditSource* pEditSource = pTextRange->GetEditSource();
396             ESelection aSelection(pTextRange->GetSelection());
397 
398             if (!bAbsorb)
399             {
400                 //  don't replace -> append at end
401                 aSelection.Adjust();
402                 aSelection.nStartPara = aSelection.nEndPara;
403                 aSelection.nStartPos  = aSelection.nEndPos;
404             }
405 
406             SvxFieldItem aItem(pHeaderField->CreateFieldItem());
407 
408             SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder();
409             pForwarder->QuickInsertField( aItem, aSelection );
410             pEditSource->UpdateData();
411 
412             //  new selection: a digit
413             aSelection.Adjust();
414             aSelection.nEndPara = aSelection.nStartPara;
415             aSelection.nEndPos = aSelection.nStartPos + 1;
416 
417             uno::Reference<text::XTextRange> xTextRange;
418             switch ( aTextData.GetPart() )
419             {
420                 case ScHeaderFooterPart::LEFT:
421                     xTextRange = aTextData.GetContentObj()->getLeftText();
422                 break;
423                 case ScHeaderFooterPart::CENTER:
424                     xTextRange = aTextData.GetContentObj()->getCenterText();
425                 break;
426                 case ScHeaderFooterPart::RIGHT:
427                     xTextRange = aTextData.GetContentObj()->getRightText();
428                 break;
429             }
430 
431             pHeaderField->InitDoc(xTextRange, std::make_unique<ScHeaderFooterEditSource>(aTextData), aSelection);
432 
433             //  for bAbsorb=FALSE, the new selection must be behind the inserted content
434             //  (the xml filter relies on this)
435             if (!bAbsorb)
436                 aSelection.nStartPos = aSelection.nEndPos;
437 
438             pTextRange->SetSelection( aSelection );
439 
440             return;
441         }
442     }
443 
444     if (!mxUnoText.is())
445         CreateUnoText_Impl();
446     mxUnoText->insertTextContent( xRange, xContent, bAbsorb );
447 }
448 
removeTextContent(const uno::Reference<text::XTextContent> & xContent)449 void SAL_CALL ScHeaderFooterTextObj::removeTextContent(
450                                             const uno::Reference<text::XTextContent>& xContent )
451 {
452     SolarMutexGuard aGuard;
453     if ( xContent.is() )
454     {
455         ScEditFieldObj* pHeaderField = comphelper::getUnoTunnelImplementation<ScEditFieldObj>(xContent);
456         if ( pHeaderField && pHeaderField->IsInserted() )
457         {
458             //! check if the field is in this cell
459             pHeaderField->DeleteField();
460             return;
461         }
462     }
463     if (!mxUnoText.is())
464         CreateUnoText_Impl();
465     mxUnoText->removeTextContent( xContent );
466 }
467 
getText()468 uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextObj::getText()
469 {
470     SolarMutexGuard aGuard;
471     if (!mxUnoText.is())
472         CreateUnoText_Impl();
473     return mxUnoText->getText();
474 }
475 
getStart()476 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getStart()
477 {
478     SolarMutexGuard aGuard;
479     if (!mxUnoText.is())
480         CreateUnoText_Impl();
481     return mxUnoText->getStart();
482 }
483 
getEnd()484 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getEnd()
485 {
486     SolarMutexGuard aGuard;
487     if (!mxUnoText.is())
488         CreateUnoText_Impl();
489     return mxUnoText->getEnd();
490 }
491 
492 // XTextFieldsSupplier
493 
getTextFields()494 uno::Reference<container::XEnumerationAccess> SAL_CALL ScHeaderFooterTextObj::getTextFields()
495 {
496     SolarMutexGuard aGuard;
497     // all fields
498     return new ScHeaderFieldsObj(aTextData);
499 }
500 
getTextFieldMasters()501 uno::Reference<container::XNameAccess> SAL_CALL ScHeaderFooterTextObj::getTextFieldMasters()
502 {
503     //  this does not exists in Calc (?)
504     return nullptr;
505 }
506 
507 // XTextRangeMover
508 
moveTextRange(const uno::Reference<text::XTextRange> & xRange,sal_Int16 nParagraphs)509 void SAL_CALL ScHeaderFooterTextObj::moveTextRange(
510                                         const uno::Reference<text::XTextRange>& xRange,
511                                         sal_Int16 nParagraphs )
512 {
513     SolarMutexGuard aGuard;
514     if (!mxUnoText.is())
515         CreateUnoText_Impl();
516     mxUnoText->moveTextRange( xRange, nParagraphs );
517 }
518 
519 // XEnumerationAccess
520 
createEnumeration()521 uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFooterTextObj::createEnumeration()
522 {
523     SolarMutexGuard aGuard;
524     if (!mxUnoText.is())
525         CreateUnoText_Impl();
526     return mxUnoText->createEnumeration();
527 }
528 
529 // XElementAccess
530 
getElementType()531 uno::Type SAL_CALL ScHeaderFooterTextObj::getElementType()
532 {
533     SolarMutexGuard aGuard;
534     if (!mxUnoText.is())
535         CreateUnoText_Impl();
536     return mxUnoText->getElementType();
537 }
538 
hasElements()539 sal_Bool SAL_CALL ScHeaderFooterTextObj::hasElements()
540 {
541     SolarMutexGuard aGuard;
542     if (!mxUnoText.is())
543         CreateUnoText_Impl();
544     return mxUnoText->hasElements();
545 }
546 
ScCellTextCursor(ScCellObj & rText)547 ScCellTextCursor::ScCellTextCursor(ScCellObj& rText) :
548     SvxUnoTextCursor( rText.GetUnoText() ),
549     mxTextObj( &rText )
550 {
551 }
552 
~ScCellTextCursor()553 ScCellTextCursor::~ScCellTextCursor() throw()
554 {
555 }
556 
557 // SvxUnoTextCursor methods reimplemented here to return the right objects:
558 
getText()559 uno::Reference<text::XText> SAL_CALL ScCellTextCursor::getText()
560 {
561     return mxTextObj.get();
562 }
563 
getStart()564 uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getStart()
565 {
566     SolarMutexGuard aGuard;
567 
568     //! use other object for range than cursor?
569 
570     ScCellTextCursor* pNew = new ScCellTextCursor( *this );
571     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
572 
573     ESelection aNewSel(GetSelection());
574     aNewSel.nEndPara = aNewSel.nStartPara;
575     aNewSel.nEndPos  = aNewSel.nStartPos;
576     pNew->SetSelection( aNewSel );
577 
578     return xRange;
579 }
580 
getEnd()581 uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getEnd()
582 {
583     SolarMutexGuard aGuard;
584 
585     //! use other object for range than cursor?
586 
587     ScCellTextCursor* pNew = new ScCellTextCursor( *this );
588     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
589 
590     ESelection aNewSel(GetSelection());
591     aNewSel.nStartPara = aNewSel.nEndPara;
592     aNewSel.nStartPos  = aNewSel.nEndPos;
593     pNew->SetSelection( aNewSel );
594 
595     return xRange;
596 }
597 
598 // XUnoTunnel
599 
600 UNO3_GETIMPLEMENTATION2_IMPL(ScCellTextCursor, SvxUnoTextCursor);
601 
ScHeaderFooterTextCursor(rtl::Reference<ScHeaderFooterTextObj> const & rText)602 ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(rtl::Reference<ScHeaderFooterTextObj> const & rText) :
603     SvxUnoTextCursor( rText->GetUnoText() ),
604     rTextObj( rText )
605 {}
606 
~ScHeaderFooterTextCursor()607 ScHeaderFooterTextCursor::~ScHeaderFooterTextCursor() throw() {};
608 
609 // SvxUnoTextCursor methods reimplemented here to return the right objects:
610 
getText()611 uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextCursor::getText()
612 {
613     SolarMutexGuard aGuard;
614     return rTextObj.get();
615 }
616 
getStart()617 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getStart()
618 {
619     SolarMutexGuard aGuard;
620 
621     //! use other object for range than cursor?
622 
623     ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this );
624     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
625 
626     ESelection aNewSel(GetSelection());
627     aNewSel.nEndPara = aNewSel.nStartPara;
628     aNewSel.nEndPos  = aNewSel.nStartPos;
629     pNew->SetSelection( aNewSel );
630 
631     return xRange;
632 }
633 
getEnd()634 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getEnd()
635 {
636     SolarMutexGuard aGuard;
637 
638     //! use other object for range than cursor?
639 
640     ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this );
641     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
642 
643     ESelection aNewSel(GetSelection());
644     aNewSel.nStartPara = aNewSel.nEndPara;
645     aNewSel.nStartPos  = aNewSel.nEndPos;
646     pNew->SetSelection( aNewSel );
647 
648     return xRange;
649 }
650 
651 // XUnoTunnel
652 
653 UNO3_GETIMPLEMENTATION2_IMPL(ScHeaderFooterTextCursor, SvxUnoTextCursor);
654 
ScDrawTextCursor(const uno::Reference<text::XText> & xParent,const SvxUnoTextBase & rText)655 ScDrawTextCursor::ScDrawTextCursor( const uno::Reference<text::XText>& xParent,
656                                     const SvxUnoTextBase& rText ) :
657     SvxUnoTextCursor( rText ),
658     xParentText( xParent )
659 
660 {
661 }
662 
~ScDrawTextCursor()663 ScDrawTextCursor::~ScDrawTextCursor() throw()
664 {
665 }
666 
667 // SvxUnoTextCursor methods reimplemented here to return the right objects:
668 
getText()669 uno::Reference<text::XText> SAL_CALL ScDrawTextCursor::getText()
670 {
671     SolarMutexGuard aGuard;
672     return xParentText;
673 }
674 
getStart()675 uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getStart()
676 {
677     SolarMutexGuard aGuard;
678 
679     //! use other object for range than cursor?
680 
681     ScDrawTextCursor* pNew = new ScDrawTextCursor( *this );
682     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
683 
684     ESelection aNewSel(GetSelection());
685     aNewSel.nEndPara = aNewSel.nStartPara;
686     aNewSel.nEndPos  = aNewSel.nStartPos;
687     pNew->SetSelection( aNewSel );
688 
689     return xRange;
690 }
691 
getEnd()692 uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getEnd()
693 {
694     SolarMutexGuard aGuard;
695 
696     //! use other object for range than cursor?
697 
698     ScDrawTextCursor* pNew = new ScDrawTextCursor( *this );
699     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
700 
701     ESelection aNewSel(GetSelection());
702     aNewSel.nStartPara = aNewSel.nEndPara;
703     aNewSel.nStartPos  = aNewSel.nEndPos;
704     pNew->SetSelection( aNewSel );
705 
706     return xRange;
707 }
708 
709 // XUnoTunnel
710 
711 UNO3_GETIMPLEMENTATION2_IMPL(ScDrawTextCursor, SvxUnoTextCursor);
712 
ScSimpleEditSourceHelper()713 ScSimpleEditSourceHelper::ScSimpleEditSourceHelper()
714 {
715     SfxItemPool* pEnginePool = EditEngine::CreatePool();
716     pEnginePool->SetDefaultMetric( MapUnit::Map100thMM );
717     pEnginePool->FreezeIdRanges();
718 
719     pEditEngine.reset( new ScFieldEditEngine(nullptr, pEnginePool, nullptr, true) );     // TRUE: become owner of pool
720     pForwarder.reset( new SvxEditEngineForwarder( *pEditEngine ) );
721     pOriginalSource.reset( new ScSimpleEditSource( pForwarder.get() ) );
722 }
723 
~ScSimpleEditSourceHelper()724 ScSimpleEditSourceHelper::~ScSimpleEditSourceHelper()
725 {
726     SolarMutexGuard aGuard;     //  needed for EditEngine dtor
727 
728     pOriginalSource.reset();
729     pForwarder.reset();
730     pEditEngine.reset();
731 }
732 
ScEditEngineTextObj()733 ScEditEngineTextObj::ScEditEngineTextObj() :
734     SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() )
735 {
736 }
737 
~ScEditEngineTextObj()738 ScEditEngineTextObj::~ScEditEngineTextObj() throw()
739 {
740 }
741 
SetText(const EditTextObject & rTextObject)742 void ScEditEngineTextObj::SetText( const EditTextObject& rTextObject )
743 {
744     GetEditEngine()->SetText( rTextObject );
745 
746     ESelection aSel;
747     ::GetSelection( aSel, GetEditSource()->GetTextForwarder() );
748     SetSelection( aSel );
749 }
750 
CreateTextObject()751 std::unique_ptr<EditTextObject> ScEditEngineTextObj::CreateTextObject()
752 {
753     return GetEditEngine()->CreateTextObject();
754 }
755 
ScCellTextData(ScDocShell * pDocSh,const ScAddress & rP)756 ScCellTextData::ScCellTextData(ScDocShell* pDocSh, const ScAddress& rP) :
757     pDocShell( pDocSh ),
758     aCellPos( rP ),
759     bDataValid( false ),
760     bInUpdate( false ),
761     bDirty( false ),
762     bDoUpdate( true )
763 {
764     if (pDocShell)
765         pDocShell->GetDocument().AddUnoObject(*this);
766 }
767 
~ScCellTextData()768 ScCellTextData::~ScCellTextData()
769 {
770     SolarMutexGuard aGuard;     //  needed for EditEngine dtor
771 
772     if (pDocShell)
773     {
774         pDocShell->GetDocument().RemoveUnoObject(*this);
775         pDocShell->GetDocument().DisposeFieldEditEngine(pEditEngine);
776     }
777     else
778         pEditEngine.reset();
779 
780     pForwarder.reset();
781 
782     pOriginalSource.reset();
783 }
784 
GetOriginalSource()785 ScCellEditSource* ScCellTextData::GetOriginalSource()
786 {
787     if (!pOriginalSource)
788         pOriginalSource.reset( new ScCellEditSource(pDocShell, aCellPos) );
789     return pOriginalSource.get();
790 }
791 
GetTextForwarder()792 SvxTextForwarder* ScCellTextData::GetTextForwarder()
793 {
794     if (!pEditEngine)
795     {
796         if ( pDocShell )
797         {
798             ScDocument& rDoc = pDocShell->GetDocument();
799             pEditEngine = rDoc.CreateFieldEditEngine();
800         }
801         else
802         {
803             SfxItemPool* pEnginePool = EditEngine::CreatePool();
804             pEnginePool->FreezeIdRanges();
805             pEditEngine.reset( new ScFieldEditEngine(nullptr, pEnginePool, nullptr, true) );
806         }
807         //  currently, GetPortions doesn't work if UpdateMode is sal_False,
808         //  this will be fixed (in EditEngine) by src600
809 //      pEditEngine->SetUpdateMode( sal_False );
810         pEditEngine->EnableUndo( false );
811         if (pDocShell)
812             pEditEngine->SetRefDevice(pDocShell->GetRefDevice());
813         else
814             pEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
815         pForwarder.reset( new SvxEditEngineForwarder(*pEditEngine) );
816     }
817 
818     if (bDataValid)
819         return pForwarder.get();
820 
821     OUString aText;
822 
823     if (pDocShell)
824     {
825         ScDocument& rDoc = pDocShell->GetDocument();
826 
827         SfxItemSet aDefaults( pEditEngine->GetEmptyItemSet() );
828         if( const ScPatternAttr* pPattern =
829                 rDoc.GetPattern( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) )
830         {
831             pPattern->FillEditItemSet( &aDefaults );
832             pPattern->FillEditParaItems( &aDefaults );  // including alignment etc. (for reading)
833         }
834 
835         ScRefCellValue aCell(rDoc, aCellPos);
836         if (aCell.meType == CELLTYPE_EDIT)
837         {
838             const EditTextObject* pObj = aCell.mpEditText;
839             pEditEngine->SetTextNewDefaults(*pObj, aDefaults);
840         }
841         else
842         {
843             sal_uInt32 nFormat = rDoc.GetNumberFormat(aCellPos);
844             ScCellFormat::GetInputString(aCell, nFormat, aText, *rDoc.GetFormatTable(), &rDoc);
845             if (!aText.isEmpty())
846                 pEditEngine->SetTextNewDefaults(aText, aDefaults);
847             else
848                 pEditEngine->SetDefaults(aDefaults);
849         }
850     }
851 
852     bDataValid = true;
853     return pForwarder.get();
854 }
855 
UpdateData()856 void ScCellTextData::UpdateData()
857 {
858     if ( bDoUpdate )
859     {
860         OSL_ENSURE(pEditEngine != nullptr, "no EditEngine for UpdateData()");
861         if ( pDocShell && pEditEngine )
862         {
863             //  during the own UpdateData call, bDataValid must not be reset,
864             //  or things like attributes after the text would be lost
865             //  (are not stored in the cell)
866             bInUpdate = true;   // prevents bDataValid from being reset
867             pDocShell->GetDocFunc().PutData(aCellPos, *pEditEngine, true); // always as text
868 
869             bInUpdate = false;
870             bDirty = false;
871         }
872     }
873     else
874         bDirty = true;
875 }
876 
Notify(SfxBroadcaster &,const SfxHint & rHint)877 void ScCellTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
878 {
879     const SfxHintId nId = rHint.GetId();
880     if ( nId == SfxHintId::Dying )
881     {
882         pDocShell = nullptr;                       // invalid now
883 
884         pForwarder.reset();
885         pEditEngine.reset();     // EditEngine uses document's pool
886     }
887     else if ( nId == SfxHintId::DataChanged )
888     {
889         if (!bInUpdate)                         // not for own UpdateData calls
890             bDataValid = false;                 // text has to be read from the cell again
891     }
892 }
893 
ScCellTextObj(ScDocShell * pDocSh,const ScAddress & rP)894 ScCellTextObj::ScCellTextObj(ScDocShell* pDocSh, const ScAddress& rP) :
895     ScCellTextData( pDocSh, rP ),
896     SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() )
897 {
898 }
899 
~ScCellTextObj()900 ScCellTextObj::~ScCellTextObj() throw()
901 {
902 }
903 
904 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
905