Move token-cache for doubles to ScInterpreterContext...
[LibreOffice.git] / sc / source / core / data / documen8.cxx
blobc7be637fb073193dd883b5cd0e4ed6082fb9cd8a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <scitems.hxx>
21 #include <editeng/eeitem.hxx>
22 #include <o3tl/make_unique.hxx>
23 #include <tools/urlobj.hxx>
24 #include <editeng/editobj.hxx>
25 #include <editeng/editstat.hxx>
26 #include <editeng/frmdiritem.hxx>
27 #include <editeng/langitem.hxx>
28 #include <sfx2/linkmgr.hxx>
29 #include <editeng/scripttypeitem.hxx>
30 #include <editeng/unolingu.hxx>
31 #include <sfx2/bindings.hxx>
32 #include <sfx2/objsh.hxx>
33 #include <sfx2/printer.hxx>
34 #include <sfx2/viewfrm.hxx>
35 #include <sfx2/viewsh.hxx>
36 #include <svl/flagitem.hxx>
37 #include <svl/intitem.hxx>
38 #include <svl/zforlist.hxx>
39 #include <svl/zformat.hxx>
40 #include <unotools/misccfg.hxx>
41 #include <sfx2/app.hxx>
42 #include <unotools/transliterationwrapper.hxx>
43 #include <unotools/securityoptions.hxx>
45 #include <vcl/virdev.hxx>
46 #include <vcl/msgbox.hxx>
48 #include <inputopt.hxx>
49 #include <global.hxx>
50 #include <table.hxx>
51 #include <column.hxx>
52 #include <poolhelp.hxx>
53 #include <docpool.hxx>
54 #include <stlpool.hxx>
55 #include <stlsheet.hxx>
56 #include <docoptio.hxx>
57 #include <viewopti.hxx>
58 #include <scextopt.hxx>
59 #include <rechead.hxx>
60 #include <ddelink.hxx>
61 #include <scmatrix.hxx>
62 #include <arealink.hxx>
63 #include <dociter.hxx>
64 #include <patattr.hxx>
65 #include <hints.hxx>
66 #include <editutil.hxx>
67 #include <progress.hxx>
68 #include <document.hxx>
69 #include <chartlis.hxx>
70 #include <chartlock.hxx>
71 #include <refupdat.hxx>
72 #include <validat.hxx>
73 #include <markdata.hxx>
74 #include <scmod.hxx>
75 #include <printopt.hxx>
76 #include <externalrefmgr.hxx>
77 #include <globstr.hrc>
78 #include <strings.hrc>
79 #include <sc.hrc>
80 #include <charthelper.hxx>
81 #include <macromgr.hxx>
82 #include <dpobject.hxx>
83 #include <docuno.hxx>
84 #include <scresid.hxx>
85 #include <columniterator.hxx>
86 #include <globalnames.hxx>
87 #include <stringutil.hxx>
88 #include <documentlinkmgr.hxx>
89 #include <scopetools.hxx>
91 #include <memory>
92 #include <utility>
94 using namespace com::sun::star;
96 namespace {
98 inline sal_uInt16 getScaleValue(SfxStyleSheetBase& rStyle, sal_uInt16 nWhich)
100 return static_cast<const SfxUInt16Item&>(rStyle.GetItemSet().Get(nWhich)).GetValue();
105 void ScDocument::ImplCreateOptions()
107 pDocOptions = new ScDocOptions();
108 pViewOptions = new ScViewOptions();
111 void ScDocument::ImplDeleteOptions()
113 delete pDocOptions;
114 delete pViewOptions;
115 delete pExtDocOptions;
118 SfxPrinter* ScDocument::GetPrinter(bool bCreateIfNotExist)
120 if ( !mpPrinter && bCreateIfNotExist )
122 auto pSet =
123 o3tl::make_unique<SfxItemSet>( *mxPoolHelper->GetDocPool(),
124 svl::Items<SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
125 SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
126 SID_PRINT_SELECTEDSHEET, SID_PRINT_SELECTEDSHEET,
127 SID_SCPRINTOPTIONS, SID_SCPRINTOPTIONS>{} );
129 ::utl::MiscCfg aMisc;
130 SfxPrinterChangeFlags nFlags = SfxPrinterChangeFlags::NONE;
131 if ( aMisc.IsPaperOrientationWarning() )
132 nFlags |= SfxPrinterChangeFlags::CHG_ORIENTATION;
133 if ( aMisc.IsPaperSizeWarning() )
134 nFlags |= SfxPrinterChangeFlags::CHG_SIZE;
135 pSet->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, static_cast<int>(nFlags) ) );
136 pSet->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, aMisc.IsNotFoundWarning() ) );
138 mpPrinter = VclPtr<SfxPrinter>::Create( std::move(pSet) );
139 mpPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
140 UpdateDrawPrinter();
141 mpPrinter->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
144 return mpPrinter;
147 void ScDocument::SetPrinter( VclPtr<SfxPrinter> const & pNewPrinter )
149 if ( pNewPrinter == mpPrinter.get() )
151 // #i6706# SetPrinter is called with the same printer again if
152 // the JobSetup has changed. In that case just call UpdateDrawPrinter
153 // (SetRefDevice for drawing layer) because of changed text sizes.
154 UpdateDrawPrinter();
156 else
158 ScopedVclPtr<SfxPrinter> pOld( mpPrinter );
159 mpPrinter = pNewPrinter;
160 UpdateDrawPrinter();
161 mpPrinter->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
163 InvalidateTextWidth(nullptr, nullptr, false); // in both cases
166 void ScDocument::SetPrintOptions()
168 if ( !mpPrinter ) GetPrinter(); // this sets mpPrinter
169 OSL_ENSURE( mpPrinter, "Error in printer creation :-/" );
171 if ( mpPrinter )
173 ::utl::MiscCfg aMisc;
174 SfxItemSet aOptSet( mpPrinter->GetOptions() );
176 SfxPrinterChangeFlags nFlags = SfxPrinterChangeFlags::NONE;
177 if ( aMisc.IsPaperOrientationWarning() )
178 nFlags |= SfxPrinterChangeFlags::CHG_ORIENTATION;
179 if ( aMisc.IsPaperSizeWarning() )
180 nFlags |= SfxPrinterChangeFlags::CHG_SIZE;
181 aOptSet.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, static_cast<int>(nFlags) ) );
182 aOptSet.Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, aMisc.IsNotFoundWarning() ) );
184 mpPrinter->SetOptions( aOptSet );
188 VirtualDevice* ScDocument::GetVirtualDevice_100th_mm()
190 if (!mpVirtualDevice_100th_mm)
192 #ifdef IOS
193 mpVirtualDevice_100th_mm = VclPtr<VirtualDevice>::Create(DeviceFormat::GRAYSCALE);
194 #else
195 mpVirtualDevice_100th_mm = VclPtr<VirtualDevice>::Create(DeviceFormat::BITMASK);
196 #endif
197 mpVirtualDevice_100th_mm->SetReferenceDevice(VirtualDevice::RefDevMode::MSO1);
198 MapMode aMapMode( mpVirtualDevice_100th_mm->GetMapMode() );
199 aMapMode.SetMapUnit( MapUnit::Map100thMM );
200 mpVirtualDevice_100th_mm->SetMapMode( aMapMode );
202 return mpVirtualDevice_100th_mm;
205 OutputDevice* ScDocument::GetRefDevice()
207 // Create printer like ref device, see Writer...
208 OutputDevice* pRefDevice = nullptr;
209 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
210 pRefDevice = GetPrinter();
211 else
212 pRefDevice = GetVirtualDevice_100th_mm();
213 return pRefDevice;
216 void ScDocument::ModifyStyleSheet( SfxStyleSheetBase& rStyleSheet,
217 const SfxItemSet& rChanges )
219 SfxItemSet& rSet = rStyleSheet.GetItemSet();
221 switch ( rStyleSheet.GetFamily() )
223 case SfxStyleFamily::Page:
225 const sal_uInt16 nOldScale = getScaleValue(rStyleSheet, ATTR_PAGE_SCALE);
226 const sal_uInt16 nOldScaleToPages = getScaleValue(rStyleSheet, ATTR_PAGE_SCALETOPAGES);
227 rSet.Put( rChanges );
228 const sal_uInt16 nNewScale = getScaleValue(rStyleSheet, ATTR_PAGE_SCALE);
229 const sal_uInt16 nNewScaleToPages = getScaleValue(rStyleSheet, ATTR_PAGE_SCALETOPAGES);
231 if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
232 InvalidateTextWidth( rStyleSheet.GetName() );
234 if( SvtLanguageOptions().IsCTLFontEnabled() )
236 const SfxPoolItem *pItem = nullptr;
237 if( rChanges.GetItemState(ATTR_WRITINGDIR, true, &pItem ) == SfxItemState::SET )
238 ScChartHelper::DoUpdateAllCharts( this );
241 break;
243 case SfxStyleFamily::Para:
245 bool bNumFormatChanged;
246 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
247 rSet, rChanges ) )
248 InvalidateTextWidth( nullptr, nullptr, bNumFormatChanged );
250 for (SCTAB nTab=0; nTab<=MAXTAB; ++nTab)
251 if (maTabs[nTab])
252 maTabs[nTab]->SetStreamValid( false );
254 sal_uLong nOldFormat =
255 static_cast<const SfxUInt32Item*>(&rSet.Get(
256 ATTR_VALUE_FORMAT ))->GetValue();
257 sal_uLong nNewFormat =
258 static_cast<const SfxUInt32Item*>(&rChanges.Get(
259 ATTR_VALUE_FORMAT ))->GetValue();
260 LanguageType eNewLang, eOldLang;
261 eNewLang = eOldLang = LANGUAGE_DONTKNOW;
262 if ( nNewFormat != nOldFormat )
264 SvNumberFormatter* pFormatter = GetFormatTable();
265 eOldLang = pFormatter->GetEntry( nOldFormat )->GetLanguage();
266 eNewLang = pFormatter->GetEntry( nNewFormat )->GetLanguage();
269 // Explanation to Items in rChanges:
270 // Set Item - take over change
271 // Dontcare - Set Default
272 // Default - No change
273 // ("no change" is not possible with PutExtended, thus the loop)
274 for (sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++)
276 const SfxPoolItem* pItem;
277 SfxItemState eState = rChanges.GetItemState( nWhich, false, &pItem );
278 if ( eState == SfxItemState::SET )
279 rSet.Put( *pItem );
280 else if ( eState == SfxItemState::DONTCARE )
281 rSet.ClearItem( nWhich );
282 // when Default nothing
285 if ( eNewLang != eOldLang )
286 rSet.Put(
287 SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
289 break;
290 default:
292 // added to avoid warnings
297 void ScDocument::CopyStdStylesFrom( const ScDocument* pSrcDoc )
299 // number format exchange list has to be handled here, too
300 NumFmtMergeHandler aNumFmtMergeHdl(this, pSrcDoc);
301 mxPoolHelper->GetStylePool()->CopyStdStylesFrom( pSrcDoc->mxPoolHelper->GetStylePool() );
304 void ScDocument::InvalidateTextWidth( const OUString& rStyleName )
306 const SCTAB nCount = GetTableCount();
307 for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
308 if ( maTabs[i]->GetPageStyle() == rStyleName )
309 InvalidateTextWidth( i );
312 void ScDocument::InvalidateTextWidth( SCTAB nTab )
314 ScAddress aAdrFrom( 0, 0, nTab );
315 ScAddress aAdrTo ( MAXCOL, MAXROW, nTab );
316 InvalidateTextWidth( &aAdrFrom, &aAdrTo, false );
319 bool ScDocument::IsPageStyleInUse( const OUString& rStrPageStyle, SCTAB* pInTab )
321 bool bInUse = false;
322 const SCTAB nCount = GetTableCount();
323 SCTAB i;
325 for ( i = 0; !bInUse && i < nCount && maTabs[i]; i++ )
326 bInUse = ( maTabs[i]->GetPageStyle() == rStrPageStyle );
328 if ( pInTab )
329 *pInTab = i-1;
331 return bInUse;
334 bool ScDocument::RemovePageStyleInUse( const OUString& rStyle )
336 bool bWasInUse = false;
337 const SCTAB nCount = GetTableCount();
339 for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
340 if ( maTabs[i]->GetPageStyle() == rStyle )
342 bWasInUse = true;
343 maTabs[i]->SetPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
346 return bWasInUse;
349 bool ScDocument::RenamePageStyleInUse( const OUString& rOld, const OUString& rNew )
351 bool bWasInUse = false;
352 const SCTAB nCount = GetTableCount();
354 for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
355 if ( maTabs[i]->GetPageStyle() == rOld )
357 bWasInUse = true;
358 maTabs[i]->SetPageStyle( rNew );
361 return bWasInUse;
364 sal_uInt8 ScDocument::GetEditTextDirection(SCTAB nTab) const
366 EEHorizontalTextDirection eRet = EE_HTEXTDIR_DEFAULT;
368 OUString aStyleName = GetPageStyle( nTab );
369 SfxStyleSheetBase* pStyle = mxPoolHelper->GetStylePool()->Find( aStyleName, SfxStyleFamily::Page );
370 if ( pStyle )
372 SfxItemSet& rStyleSet = pStyle->GetItemSet();
373 SvxFrameDirection eDirection =
374 static_cast<const SvxFrameDirectionItem&>(rStyleSet.Get( ATTR_WRITINGDIR )).GetValue();
376 if ( eDirection == SvxFrameDirection::Horizontal_LR_TB )
377 eRet = EE_HTEXTDIR_L2R;
378 else if ( eDirection == SvxFrameDirection::Horizontal_RL_TB )
379 eRet = EE_HTEXTDIR_R2L;
380 // else (invalid for EditEngine): keep "default"
383 return sal::static_int_cast<sal_uInt8>(eRet);
386 ScMacroManager* ScDocument::GetMacroManager()
388 if (!mpMacroMgr.get())
389 mpMacroMgr.reset(new ScMacroManager(this));
390 return mpMacroMgr.get();
393 void ScDocument::FillMatrix(
394 ScMatrix& rMat, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, svl::SharedStringPool* pPool ) const
396 const ScTable* pTab = FetchTable(nTab);
397 if (!pTab)
398 return;
400 if (nCol1 > nCol2 || nRow1 > nRow2)
401 return;
403 SCSIZE nC, nR;
404 rMat.GetDimensions(nC, nR);
405 if (static_cast<SCROW>(nR) != nRow2 - nRow1 + 1 || static_cast<SCCOL>(nC) != nCol2 - nCol1 + 1)
406 return;
408 pTab->FillMatrix(rMat, nCol1, nRow1, nCol2, nRow2, pPool);
411 void ScDocument::SetFormulaResults( const ScAddress& rTopPos, const double* pResults, size_t nLen )
413 ScTable* pTab = FetchTable(rTopPos.Tab());
414 if (!pTab)
415 return;
417 pTab->SetFormulaResults(rTopPos.Col(), rTopPos.Row(), pResults, nLen);
420 void ScDocument::SetFormulaResults(
421 const ScAddress& rTopPos, const formula::FormulaConstTokenRef* pResults, size_t nLen )
423 ScTable* pTab = FetchTable(rTopPos.Tab());
424 if (!pTab)
425 return;
427 pTab->SetFormulaResults(rTopPos.Col(), rTopPos.Row(), pResults, nLen);
430 ScDocumentThreadSpecific ScDocument::CalculateInColumnInThread( ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
432 ScTable* pTab = FetchTable(rTopPos.Tab());
433 if (!pTab)
434 return maNonThreaded;
436 assert(mbThreadedGroupCalcInProgress);
438 maThreadSpecific.SetupFromNonThreadedData(maNonThreaded);
439 pTab->CalculateInColumnInThread(rContext, rTopPos.Col(), rTopPos.Row(), nLen, nThisThread, nThreadsTotal);
441 assert(mbThreadedGroupCalcInProgress);
443 return maThreadSpecific;
446 void ScDocument::HandleStuffAfterParallelCalculation( const ScAddress& rTopPos, size_t nLen )
448 ScTable* pTab = FetchTable(rTopPos.Tab());
449 if (!pTab)
450 return;
452 pTab->HandleStuffAfterParallelCalculation(rTopPos.Col(), rTopPos.Row(), nLen);
455 void ScDocument::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
456 bool bNumFormatChanged )
458 bool bBroadcast = (bNumFormatChanged && GetDocOptions().IsCalcAsShown() && !IsImportingXML() && !IsClipboard());
459 if ( pAdrFrom && !pAdrTo )
461 const SCTAB nTab = pAdrFrom->Tab();
463 if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
464 maTabs[nTab]->InvalidateTextWidth( pAdrFrom, nullptr, bNumFormatChanged, bBroadcast );
466 else
468 const SCTAB nTabStart = pAdrFrom ? pAdrFrom->Tab() : 0;
469 const SCTAB nTabEnd = pAdrTo ? pAdrTo->Tab() : MAXTAB;
471 for ( SCTAB nTab=nTabStart; nTab<=nTabEnd && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
472 if ( maTabs[nTab] )
473 maTabs[nTab]->InvalidateTextWidth( pAdrFrom, pAdrTo, bNumFormatChanged, bBroadcast );
477 #define CALCMAX 1000 // Calculations
479 namespace {
481 class IdleCalcTextWidthScope
483 ScDocument& mrDoc;
484 ScAddress& mrCalcPos;
485 MapMode maOldMapMode;
486 sal_uInt64 mnStartTime;
487 ScStyleSheetPool* mpStylePool;
488 sal_uInt16 mnOldSearchMask;
489 SfxStyleFamily meOldFamily;
490 bool mbNeedMore;
491 bool mbProgress;
493 public:
494 IdleCalcTextWidthScope(ScDocument& rDoc, ScAddress& rCalcPos) :
495 mrDoc(rDoc),
496 mrCalcPos(rCalcPos),
497 mnStartTime(tools::Time::GetSystemTicks()),
498 mpStylePool(rDoc.GetStyleSheetPool()),
499 mnOldSearchMask(mpStylePool->GetSearchMask()),
500 meOldFamily(mpStylePool->GetSearchFamily()),
501 mbNeedMore(false),
502 mbProgress(false)
504 // The old search mask / family flags must be restored so that e.g.
505 // the styles dialog shows correct listing when it's opened in-between
506 // the calls.
508 mrDoc.EnableIdle(false);
509 mpStylePool->SetSearchMask(SfxStyleFamily::Page);
512 ~IdleCalcTextWidthScope() COVERITY_NOEXCEPT_FALSE
514 SfxPrinter* pDev = mrDoc.GetPrinter();
515 if (pDev)
516 pDev->SetMapMode(maOldMapMode);
518 if (mbProgress)
519 ScProgress::DeleteInterpretProgress();
521 mpStylePool->SetSearchMask(meOldFamily, mnOldSearchMask);
522 mrDoc.EnableIdle(true);
525 SCTAB Tab() const { return mrCalcPos.Tab(); }
526 SCCOL Col() const { return mrCalcPos.Col(); }
527 SCROW Row() const { return mrCalcPos.Row(); }
529 void setTab(SCTAB nTab) { mrCalcPos.SetTab(nTab); }
530 void setCol(SCCOL nCol) { mrCalcPos.SetCol(nCol); }
531 void setRow(SCROW nRow) { mrCalcPos.SetRow(nRow); }
533 void incTab() { mrCalcPos.IncTab(); }
534 void incCol(SCCOL nInc) { mrCalcPos.IncCol(nInc); }
536 void setOldMapMode(const MapMode& rOldMapMode) { maOldMapMode = rOldMapMode; }
538 void setNeedMore(bool b) { mbNeedMore = b; }
539 bool getNeedMore() const { return mbNeedMore; }
541 sal_uInt64 getStartTime() const { return mnStartTime; }
543 void createProgressBar()
545 ScProgress::CreateInterpretProgress(&mrDoc, false);
546 mbProgress = true;
549 bool hasProgressBar() const { return mbProgress; }
551 ScStyleSheetPool* getStylePool() { return mpStylePool; }
556 bool ScDocument::IdleCalcTextWidth() // true = try next again
558 // #i75610# if a printer hasn't been set or created yet, don't create one for this
559 if (!mbIdleEnabled || IsInLinkUpdate() || GetPrinter(false) == nullptr)
560 return false;
562 IdleCalcTextWidthScope aScope(*this, aCurTextWidthCalcPos);
564 if (!ValidRow(aScope.Row()))
566 aScope.setRow(0);
567 aScope.incCol(-1);
570 if (aScope.Col() < 0)
572 aScope.setCol(MAXCOL);
573 aScope.incTab();
576 if (!ValidTab(aScope.Tab()) || aScope.Tab() >= static_cast<SCTAB>(maTabs.size()) || !maTabs[aScope.Tab()])
577 aScope.setTab(0);
579 ScTable* pTab = maTabs[aScope.Tab()];
580 ScStyleSheet* pStyle = static_cast<ScStyleSheet*>(aScope.getStylePool()->Find(pTab->aPageStyle, SfxStyleFamily::Page));
581 OSL_ENSURE( pStyle, "Missing StyleSheet :-/" );
583 if (!pStyle || getScaleValue(*pStyle, ATTR_PAGE_SCALETOPAGES) == 0)
585 // Move to the next sheet as the current one has scale-to-pages set,
586 // and bail out.
587 aScope.incTab();
588 return false;
591 sal_uInt16 nZoom = getScaleValue(*pStyle, ATTR_PAGE_SCALE);
592 Fraction aZoomFract(nZoom, 100);
594 // Start at specified cell position (nCol, nRow, nTab).
595 ScColumn* pCol = &pTab->aCol[aScope.Col()];
596 std::unique_ptr<ScColumnTextWidthIterator> pColIter(new ScColumnTextWidthIterator(*pCol, aScope.Row(), MAXROW));
598 OutputDevice* pDev = nullptr;
599 sal_uInt16 nRestart = 0;
600 sal_uInt16 nCount = 0;
601 while ( (nZoom > 0) && (nCount < CALCMAX) && (nRestart < 2) )
603 if (pColIter->hasCell())
605 // More cell in this column.
606 SCROW nRow = pColIter->getPos();
607 aScope.setRow(nRow);
609 if (pColIter->getValue() == TEXTWIDTH_DIRTY)
611 // Calculate text width for this cell.
612 double nPPTX = 0.0;
613 double nPPTY = 0.0;
614 if (!pDev)
616 pDev = GetPrinter();
617 aScope.setOldMapMode(pDev->GetMapMode());
618 pDev->SetMapMode(MapMode(MapUnit::MapPixel)); // Important for GetNeededSize
620 Point aPix1000 = pDev->LogicToPixel(Point(1000,1000), MapMode(MapUnit::MapTwip));
621 nPPTX = aPix1000.X() / 1000.0;
622 nPPTY = aPix1000.Y() / 1000.0;
625 if (!aScope.hasProgressBar() && pCol->IsFormulaDirty(nRow))
626 aScope.createProgressBar();
628 sal_uInt16 nNewWidth = (sal_uInt16)GetNeededSize(
629 aScope.Col(), aScope.Row(), aScope.Tab(),
630 pDev, nPPTX, nPPTY, aZoomFract,aZoomFract, true, true); // bTotalSize
632 pColIter->setValue(nNewWidth);
633 aScope.setNeedMore(true);
635 pColIter->next();
637 else
639 // No more cell in this column. Move to the left column and start at row 0.
641 bool bNewTab = false;
643 aScope.setRow(0);
644 aScope.incCol(-1);
646 if (aScope.Col() < 0)
648 // No more column to the left. Move to the right-most column of the next sheet.
649 aScope.setCol(MAXCOL);
650 aScope.incTab();
651 bNewTab = true;
654 if (!ValidTab(aScope.Tab()) || aScope.Tab() >= static_cast<SCTAB>(maTabs.size()) || !maTabs[aScope.Tab()] )
656 // Sheet doesn't exist at specified sheet position. Restart at sheet 0.
657 aScope.setTab(0);
658 nRestart++;
659 bNewTab = true;
662 if ( nRestart < 2 )
664 if ( bNewTab )
666 pTab = maTabs[aScope.Tab()];
667 pStyle = static_cast<ScStyleSheet*>(aScope.getStylePool()->Find(
668 pTab->aPageStyle, SfxStyleFamily::Page));
670 if ( pStyle )
672 // Check if the scale-to-pages setting is set. If
673 // set, we exit the loop. If not, get the page
674 // scale factor of the new sheet.
675 if (getScaleValue(*pStyle, ATTR_PAGE_SCALETOPAGES) == 0)
677 nZoom = getScaleValue(*pStyle, ATTR_PAGE_SCALE);
678 aZoomFract = Fraction(nZoom, 100);
680 else
681 nZoom = 0;
683 else
685 OSL_FAIL( "Missing StyleSheet :-/" );
689 if ( nZoom > 0 )
691 pCol = &pTab->aCol[aScope.Col()];
692 pColIter.reset(new ScColumnTextWidthIterator(*pCol, aScope.Row(), MAXROW));
694 else
696 aScope.incTab(); // Move to the next sheet as the current one has scale-to-pages set.
697 return false;
702 ++nCount;
704 // Quit if either 1) its duration exceeds 50 ms, or 2) there is any
705 // pending event after processing 32 cells.
706 VclInputFlags ABORT_EVENTS = VCL_INPUT_ANY;
707 ABORT_EVENTS &= ~VclInputFlags::TIMER;
708 ABORT_EVENTS &= ~VclInputFlags::OTHER;
709 if ((50L < tools::Time::GetSystemTicks() - aScope.getStartTime()) || (nCount > 31 && Application::AnyInput(ABORT_EVENTS)))
710 nCount = CALCMAX;
713 return aScope.getNeedMore();
716 void ScDocument::RepaintRange( const ScRange& rRange )
718 if ( bIsVisible && mpShell )
720 ScModelObj* pModel = ScModelObj::getImplementation( mpShell->GetModel() );
721 if ( pModel )
722 pModel->RepaintRange( rRange ); // locked repaints are checked there
726 void ScDocument::RepaintRange( const ScRangeList& rRange )
728 if ( bIsVisible && mpShell )
730 ScModelObj* pModel = ScModelObj::getImplementation( mpShell->GetModel() );
731 if ( pModel )
732 pModel->RepaintRange( rRange ); // locked repaints are checked there
736 void ScDocument::SaveDdeLinks(SvStream& rStream) const
738 // when 4.0-Export, remove all with mode != DEFAULT
739 bool bExport40 = ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_40 );
741 const ::sfx2::SvBaseLinks& rLinks = GetLinkManager()->GetLinks();
742 sal_uInt16 nCount = rLinks.size();
744 // Count them first
746 sal_uInt16 nDdeCount = 0;
747 sal_uInt16 i;
748 for (i=0; i<nCount; i++)
750 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
751 if (ScDdeLink* pLink = dynamic_cast<ScDdeLink*>(pBase))
752 if ( !bExport40 || pLink->GetMode() == SC_DDE_DEFAULT )
753 ++nDdeCount;
756 // Header
758 ScMultipleWriteHeader aHdr( rStream );
759 rStream.WriteUInt16( nDdeCount );
761 // Save links
763 for (i=0; i<nCount; i++)
765 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
766 if (ScDdeLink* pLink = dynamic_cast<ScDdeLink*>(pBase))
768 if ( !bExport40 || pLink->GetMode() == SC_DDE_DEFAULT )
769 pLink->Store( rStream, aHdr );
774 void ScDocument::LoadDdeLinks(SvStream& rStream)
776 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(bAutoCalc);
777 if (!pMgr)
778 return;
780 ScMultipleReadHeader aHdr( rStream );
782 sal_uInt16 nCount(0);
783 rStream.ReadUInt16( nCount );
785 const rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
786 const size_t nMinStringSize = eCharSet == RTL_TEXTENCODING_UNICODE ? sizeof(sal_uInt32) : sizeof(sal_uInt16);
787 const size_t nMinRecordSize = 1 + nMinStringSize*3;
788 const size_t nMaxRecords = rStream.remainingSize() / nMinRecordSize;
789 if (nCount > nMaxRecords)
791 SAL_WARN("sc", "Parsing error: " << nMaxRecords <<
792 " max possible entries, but " << nCount << " claimed, truncating");
793 nCount = nMaxRecords;
796 for (sal_uInt16 i=0; i<nCount; ++i)
798 ScDdeLink* pLink = new ScDdeLink( this, rStream, aHdr );
799 pMgr->InsertDDELink(pLink, pLink->GetAppl(), pLink->GetTopic(), pLink->GetItem());
803 void ScDocument::SetInLinkUpdate(bool bSet)
805 // called from TableLink and AreaLink
807 OSL_ENSURE( bInLinkUpdate != bSet, "SetInLinkUpdate twice" );
808 bInLinkUpdate = bSet;
811 bool ScDocument::IsInLinkUpdate() const
813 return bInLinkUpdate || IsInDdeLinkUpdate();
816 void ScDocument::UpdateExternalRefLinks(vcl::Window* pWin)
818 if (!pExternalRefMgr.get())
819 return;
821 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(bAutoCalc);
822 if (!pMgr)
823 return;
825 const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
826 sal_uInt16 nCount = rLinks.size();
828 bool bAny = false;
830 // Collect all the external ref links first.
831 std::vector<ScExternalRefLink*> aRefLinks;
832 for (sal_uInt16 i = 0; i < nCount; ++i)
834 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
835 ScExternalRefLink* pRefLink = dynamic_cast<ScExternalRefLink*>(pBase);
836 if (pRefLink)
837 aRefLinks.push_back(pRefLink);
840 sc::WaitPointerSwitch aWaitSwitch(pWin);
842 pExternalRefMgr->enableDocTimer(false);
843 ScProgress aProgress(GetDocumentShell(), ScResId(SCSTR_UPDATE_EXTDOCS), aRefLinks.size(), true);
844 for (size_t i = 0, n = aRefLinks.size(); i < n; ++i)
846 aProgress.SetState(i+1);
848 ScExternalRefLink* pRefLink = aRefLinks[i];
849 if (pRefLink->Update())
851 bAny = true;
852 continue;
855 // Update failed. Notify the user.
857 OUString aFile;
858 sfx2::LinkManager::GetDisplayNames(pRefLink, nullptr, &aFile);
859 // Decode encoded URL for display friendliness.
860 INetURLObject aUrl(aFile,INetURLObject::EncodeMechanism::WasEncoded);
861 aFile = aUrl.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous);
863 OUStringBuffer aBuf;
864 aBuf.append(ScResId(SCSTR_EXTDOC_NOT_LOADED));
865 aBuf.append("\n\n");
866 aBuf.append(aFile);
867 ScopedVclPtrInstance< MessageDialog > aBox(pWin, aBuf.makeStringAndClear());
868 aBox->Execute();
871 pExternalRefMgr->enableDocTimer(true);
873 if (bAny)
875 TrackFormulas();
876 mpShell->Broadcast( SfxHint(SfxHintId::ScDataChanged) );
878 // #i101960# set document modified, as in TrackTimeHdl for DDE links
879 if (!mpShell->IsModified())
881 mpShell->SetModified();
882 SfxBindings* pBindings = GetViewBindings();
883 if (pBindings)
885 pBindings->Invalidate( SID_SAVEDOC );
886 pBindings->Invalidate( SID_DOC_MODIFIED );
892 void ScDocument::CopyDdeLinks( ScDocument* pDestDoc ) const
894 if (bIsClip) // Create from Stream
896 if (pClipData)
898 pClipData->Seek(0);
899 pDestDoc->LoadDdeLinks(*pClipData);
902 return;
905 const sfx2::LinkManager* pMgr = GetDocLinkManager().getExistingLinkManager();
906 if (!pMgr)
907 return;
909 sfx2::LinkManager* pDestMgr = pDestDoc->GetDocLinkManager().getLinkManager(pDestDoc->bAutoCalc);
910 if (!pDestMgr)
911 return;
913 const sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
914 for (const auto & rLink : rLinks)
916 const sfx2::SvBaseLink* pBase = rLink.get();
917 if (const ScDdeLink* p = dynamic_cast<const ScDdeLink*>(pBase))
919 ScDdeLink* pNew = new ScDdeLink(pDestDoc, *p);
920 pDestMgr->InsertDDELink(
921 pNew, pNew->GetAppl(), pNew->GetTopic(), pNew->GetItem());
926 namespace {
928 /** Tries to find the specified DDE link.
929 @param pnDdePos (out-param) if not 0, the index of the DDE link is returned here
930 (does not include other links from link manager).
931 @return The DDE link, if it exists, otherwise 0. */
932 ScDdeLink* lclGetDdeLink(
933 const sfx2::LinkManager* pLinkManager,
934 const OUString& rAppl, const OUString& rTopic, const OUString& rItem, sal_uInt8 nMode,
935 size_t* pnDdePos = nullptr )
937 if( pLinkManager )
939 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
940 size_t nCount = rLinks.size();
941 if( pnDdePos ) *pnDdePos = 0;
942 for( size_t nIndex = 0; nIndex < nCount; ++nIndex )
944 ::sfx2::SvBaseLink* pLink = rLinks[ nIndex ].get();
945 if( ScDdeLink* pDdeLink = dynamic_cast<ScDdeLink*>( pLink ) )
947 if( (pDdeLink->GetAppl() == rAppl) &&
948 (pDdeLink->GetTopic() == rTopic) &&
949 (pDdeLink->GetItem() == rItem) &&
950 ((nMode == SC_DDE_IGNOREMODE) || (nMode == pDdeLink->GetMode())) )
951 return pDdeLink;
952 if( pnDdePos ) ++*pnDdePos;
956 return nullptr;
959 /** Returns a pointer to the specified DDE link.
960 @param nDdePos Index of the DDE link (does not include other links from link manager).
961 @return The DDE link, if it exists, otherwise 0. */
962 ScDdeLink* lclGetDdeLink( const sfx2::LinkManager* pLinkManager, size_t nDdePos )
964 if( pLinkManager )
966 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
967 size_t nCount = rLinks.size();
968 size_t nDdeIndex = 0; // counts only the DDE links
969 for( size_t nIndex = 0; nIndex < nCount; ++nIndex )
971 ::sfx2::SvBaseLink* pLink = rLinks[ nIndex ].get();
972 if( ScDdeLink* pDdeLink = dynamic_cast<ScDdeLink*>( pLink ) )
974 if( nDdeIndex == nDdePos )
975 return pDdeLink;
976 ++nDdeIndex;
980 return nullptr;
983 } // namespace
985 bool ScDocument::FindDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem,
986 sal_uInt8 nMode, size_t& rnDdePos )
988 return lclGetDdeLink( GetLinkManager(), rAppl, rTopic, rItem, nMode, &rnDdePos ) != nullptr;
991 bool ScDocument::GetDdeLinkData( size_t nDdePos, OUString& rAppl, OUString& rTopic, OUString& rItem ) const
993 if( const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
995 rAppl = pDdeLink->GetAppl();
996 rTopic = pDdeLink->GetTopic();
997 rItem = pDdeLink->GetItem();
998 return true;
1000 return false;
1003 bool ScDocument::GetDdeLinkMode( size_t nDdePos, sal_uInt8& rnMode ) const
1005 if( const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
1007 rnMode = pDdeLink->GetMode();
1008 return true;
1010 return false;
1013 const ScMatrix* ScDocument::GetDdeLinkResultMatrix( size_t nDdePos ) const
1015 const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos );
1016 return pDdeLink ? pDdeLink->GetResult() : nullptr;
1019 bool ScDocument::CreateDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem, sal_uInt8 nMode, const ScMatrixRef& pResults )
1021 /* Create a DDE link without updating it (i.e. for Excel import), to prevent
1022 unwanted connections. First try to find existing link. Set result array
1023 on existing and new links. */
1024 //TODO: store DDE links additionally at document (for efficiency)?
1025 OSL_ENSURE( nMode != SC_DDE_IGNOREMODE, "ScDocument::CreateDdeLink - SC_DDE_IGNOREMODE not allowed here" );
1027 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(bAutoCalc);
1028 if (!pMgr)
1029 return false;
1031 if (nMode != SC_DDE_IGNOREMODE)
1033 ScDdeLink* pDdeLink = lclGetDdeLink(pMgr, rAppl, rTopic, rItem, nMode);
1034 if( !pDdeLink )
1036 // create a new DDE link, but without TryUpdate
1037 pDdeLink = new ScDdeLink( this, rAppl, rTopic, rItem, nMode );
1038 pMgr->InsertDDELink(pDdeLink, rAppl, rTopic, rItem);
1041 // insert link results
1042 if( pResults )
1043 pDdeLink->SetResult( pResults );
1045 return true;
1047 return false;
1050 bool ScDocument::SetDdeLinkResultMatrix( size_t nDdePos, const ScMatrixRef& pResults )
1052 if( ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
1054 pDdeLink->SetResult( pResults );
1055 return true;
1057 return false;
1060 bool ScDocument::HasAreaLinks() const
1062 const sfx2::LinkManager* pMgr = GetDocLinkManager().getExistingLinkManager();
1063 if (!pMgr)
1064 return false;
1066 const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1067 sal_uInt16 nCount = rLinks.size();
1068 for (sal_uInt16 i=0; i<nCount; i++)
1069 if (nullptr != dynamic_cast<const ScAreaLink* >(rLinks[i].get()))
1070 return true;
1072 return false;
1075 void ScDocument::UpdateAreaLinks()
1077 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(false);
1078 if (!pMgr)
1079 return;
1081 const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1082 for (const auto & rLink : rLinks)
1084 ::sfx2::SvBaseLink* pBase = rLink.get();
1085 if (dynamic_cast<const ScAreaLink*>( pBase) != nullptr)
1086 pBase->Update();
1090 void ScDocument::DeleteAreaLinksOnTab( SCTAB nTab )
1092 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(false);
1093 if (!pMgr)
1094 return;
1096 const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1097 sfx2::SvBaseLinks::size_type nPos = 0;
1098 while ( nPos < rLinks.size() )
1100 const ::sfx2::SvBaseLink* pBase = rLinks[nPos].get();
1101 const ScAreaLink* pLink = dynamic_cast<const ScAreaLink*>(pBase);
1102 if (pLink && pLink->GetDestArea().aStart.Tab() == nTab)
1103 pMgr->Remove(nPos);
1104 else
1105 ++nPos;
1109 void ScDocument::UpdateRefAreaLinks( UpdateRefMode eUpdateRefMode,
1110 const ScRange& rRange, SCCOL nDx, SCROW nDy, SCTAB nDz )
1112 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(false);
1113 if (!pMgr)
1114 return;
1116 bool bAnyUpdate = false;
1118 const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1119 sal_uInt16 nCount = rLinks.size();
1120 for (sal_uInt16 i=0; i<nCount; i++)
1122 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
1123 if (ScAreaLink* pLink = dynamic_cast<ScAreaLink*>(pBase))
1125 ScRange aOutRange = pLink->GetDestArea();
1127 SCCOL nCol1 = aOutRange.aStart.Col();
1128 SCROW nRow1 = aOutRange.aStart.Row();
1129 SCTAB nTab1 = aOutRange.aStart.Tab();
1130 SCCOL nCol2 = aOutRange.aEnd.Col();
1131 SCROW nRow2 = aOutRange.aEnd.Row();
1132 SCTAB nTab2 = aOutRange.aEnd.Tab();
1134 ScRefUpdateRes eRes =
1135 ScRefUpdate::Update( this, eUpdateRefMode,
1136 rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
1137 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
1138 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1139 if ( eRes != UR_NOTHING )
1141 pLink->SetDestArea( ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ) );
1142 bAnyUpdate = true;
1147 if ( bAnyUpdate )
1149 // #i52120# Look for duplicates (after updating all positions).
1150 // If several links start at the same cell, the one with the lower index is removed
1151 // (file format specifies only one link definition for a cell).
1153 sal_uInt16 nFirstIndex = 0;
1154 while ( nFirstIndex < nCount )
1156 bool bFound = false;
1157 ::sfx2::SvBaseLink* pFirst = rLinks[nFirstIndex].get();
1158 if (ScAreaLink* pFirstLink = dynamic_cast<ScAreaLink*>(pFirst))
1160 ScAddress aFirstPos = pFirstLink->GetDestArea().aStart;
1161 for ( sal_uInt16 nSecondIndex = nFirstIndex + 1; nSecondIndex < nCount && !bFound; ++nSecondIndex )
1163 ::sfx2::SvBaseLink* pSecond = rLinks[nSecondIndex].get();
1164 ScAreaLink* pSecondLink = dynamic_cast<ScAreaLink*>(pSecond);
1165 if (pSecondLink && pSecondLink->GetDestArea().aStart == aFirstPos)
1167 // remove the first link, exit the inner loop, don't increment nFirstIndex
1168 pMgr->Remove(pFirst);
1169 nCount = rLinks.size();
1170 bFound = true;
1174 if (!bFound)
1175 ++nFirstIndex;
1180 // TimerDelays etc.
1181 void ScDocument::KeyInput()
1183 if ( pChartListenerCollection->hasListeners() )
1184 pChartListenerCollection->StartTimer();
1185 if( apTemporaryChartLock.get() )
1186 apTemporaryChartLock->StartOrContinueLocking();
1189 SfxBindings* ScDocument::GetViewBindings()
1191 // used to invalidate slots after changes to this document
1193 if ( !mpShell )
1194 return nullptr; // no ObjShell -> no view
1196 // first check current view
1197 SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1198 if ( pViewFrame && pViewFrame->GetObjectShell() != mpShell ) // wrong document?
1199 pViewFrame = nullptr;
1201 // otherwise use first view for this doc
1202 if ( !pViewFrame )
1203 pViewFrame = SfxViewFrame::GetFirst( mpShell );
1205 if (pViewFrame)
1206 return &pViewFrame->GetBindings();
1207 else
1208 return nullptr;
1211 void ScDocument::TransliterateText( const ScMarkData& rMultiMark, TransliterationFlags nType )
1213 OSL_ENSURE( rMultiMark.IsMultiMarked(), "TransliterateText: no selection" );
1215 utl::TransliterationWrapper aTransliterationWrapper( comphelper::getProcessComponentContext(), nType );
1216 bool bConsiderLanguage = aTransliterationWrapper.needLanguageForTheMode();
1217 LanguageType nLanguage = LANGUAGE_SYSTEM;
1219 std::unique_ptr<ScEditEngineDefaulter> pEngine; // not using mpEditEngine member because of defaults
1221 SCTAB nCount = GetTableCount();
1222 ScMarkData::const_iterator itr = rMultiMark.begin(), itrEnd = rMultiMark.end();
1223 for (; itr != itrEnd && *itr < nCount; ++itr)
1224 if ( maTabs[*itr] )
1226 SCTAB nTab = *itr;
1227 SCCOL nCol = 0;
1228 SCROW nRow = 0;
1230 bool bFound = rMultiMark.IsCellMarked( nCol, nRow );
1231 if (!bFound)
1232 bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
1234 while (bFound)
1236 ScRefCellValue aCell(*this, ScAddress(nCol, nRow, nTab));
1238 // fdo#32786 TITLE_CASE/SENTENCE_CASE need the extra handling in EditEngine (loop over words/sentences).
1239 // Still use TransliterationWrapper directly for text cells with other transliteration types,
1240 // for performance reasons.
1241 if (aCell.meType == CELLTYPE_EDIT ||
1242 (aCell.meType == CELLTYPE_STRING &&
1243 ( nType == TransliterationFlags::SENTENCE_CASE || nType == TransliterationFlags::TITLE_CASE)))
1245 if (!pEngine)
1246 pEngine.reset(new ScFieldEditEngine(this, GetEnginePool(), GetEditPool()));
1248 // defaults from cell attributes must be set so right language is used
1249 const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
1250 SfxItemSet* pDefaults = new SfxItemSet( pEngine->GetEmptyItemSet() );
1251 if ( ScStyleSheet* pPreviewStyle = GetPreviewCellStyle( nCol, nRow, nTab ) )
1253 std::unique_ptr<ScPatternAttr> pPreviewPattern(new ScPatternAttr( *pPattern ));
1254 pPreviewPattern->SetStyleSheet(pPreviewStyle);
1255 pPreviewPattern->FillEditItemSet( pDefaults );
1257 else
1259 SfxItemSet* pFontSet = GetPreviewFont( nCol, nRow, nTab );
1260 pPattern->FillEditItemSet( pDefaults, pFontSet );
1262 pEngine->SetDefaults( pDefaults );
1263 if (aCell.meType == CELLTYPE_STRING)
1264 pEngine->SetText(aCell.mpString->getString());
1265 else if (aCell.mpEditText)
1266 pEngine->SetText(*aCell.mpEditText);
1268 pEngine->ClearModifyFlag();
1270 sal_Int32 nLastPar = pEngine->GetParagraphCount();
1271 if (nLastPar)
1272 --nLastPar;
1273 sal_Int32 nTxtLen = pEngine->GetTextLen(nLastPar);
1274 ESelection aSelAll( 0, 0, nLastPar, nTxtLen );
1276 pEngine->TransliterateText( aSelAll, nType );
1278 if ( pEngine->IsModified() )
1280 ScEditAttrTester aTester( pEngine.get() );
1281 if ( aTester.NeedsObject() )
1283 // remove defaults (paragraph attributes) before creating text object
1284 SfxItemSet* pEmpty = new SfxItemSet( pEngine->GetEmptyItemSet() );
1285 pEngine->SetDefaults( pEmpty );
1287 // The cell will take ownership of the text object instance.
1288 SetEditText(ScAddress(nCol,nRow,nTab), pEngine->CreateTextObject());
1290 else
1292 ScSetStringParam aParam;
1293 aParam.setTextInput();
1294 SetString(ScAddress(nCol,nRow,nTab), pEngine->GetText(), &aParam);
1299 else if (aCell.meType == CELLTYPE_STRING)
1301 OUString aOldStr = aCell.mpString->getString();
1302 sal_Int32 nOldLen = aOldStr.getLength();
1304 if ( bConsiderLanguage )
1306 SvtScriptType nScript = GetStringScriptType( aOldStr ); //TODO: cell script type?
1307 sal_uInt16 nWhich = ( nScript == SvtScriptType::ASIAN ) ? ATTR_CJK_FONT_LANGUAGE :
1308 ( ( nScript == SvtScriptType::COMPLEX ) ? ATTR_CTL_FONT_LANGUAGE :
1309 ATTR_FONT_LANGUAGE );
1310 nLanguage = static_cast<const SvxLanguageItem*>(GetAttr( nCol, nRow, nTab, nWhich ))->GetValue();
1313 uno::Sequence<sal_Int32> aOffsets;
1314 OUString aNewStr = aTransliterationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets );
1316 if ( aNewStr != aOldStr )
1318 ScSetStringParam aParam;
1319 aParam.setTextInput();
1320 SetString(ScAddress(nCol,nRow,nTab), aNewStr, &aParam);
1323 bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
1328 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */