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