LibreOffice Module sc (master)  1
documen8.cxx
Go to the documentation of this file.
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 <scitems.hxx>
21 #include <comphelper/fileformat.h>
24 #include <officecfg/Office/Common.hxx>
25 #include <tools/urlobj.hxx>
26 #include <editeng/frmdiritem.hxx>
27 #include <editeng/langitem.hxx>
28 #include <sfx2/linkmgr.hxx>
29 #include <sfx2/bindings.hxx>
30 #include <sfx2/objsh.hxx>
31 #include <sfx2/printer.hxx>
32 #include <sfx2/viewfrm.hxx>
33 #include <sfx2/viewsh.hxx>
34 #include <svl/flagitem.hxx>
35 #include <svl/intitem.hxx>
36 #include <svl/zforlist.hxx>
37 #include <svl/zformat.hxx>
39 #include <sal/log.hxx>
40 #include <osl/diagnose.h>
41 
42 #include <vcl/svapp.hxx>
43 #include <vcl/virdev.hxx>
44 #include <vcl/weld.hxx>
45 #include <vcl/TaskStopwatch.hxx>
46 
47 #include <inputopt.hxx>
48 #include <global.hxx>
49 #include <table.hxx>
50 #include <column.hxx>
51 #include <poolhelp.hxx>
52 #include <docpool.hxx>
53 #include <stlpool.hxx>
54 #include <stlsheet.hxx>
55 #include <docoptio.hxx>
56 #include <viewopti.hxx>
57 #include <scextopt.hxx>
58 #include <rechead.hxx>
59 #include <ddelink.hxx>
60 #include <scmatrix.hxx>
61 #include <arealink.hxx>
62 #include <patattr.hxx>
63 #include <editutil.hxx>
64 #include <progress.hxx>
65 #include <document.hxx>
66 #include <chartlis.hxx>
67 #include <chartlock.hxx>
68 #include <refupdat.hxx>
69 #include <markdata.hxx>
70 #include <scmod.hxx>
71 #include <externalrefmgr.hxx>
72 #include <globstr.hrc>
73 #include <strings.hrc>
74 #include <sc.hrc>
75 #include <charthelper.hxx>
76 #include <macromgr.hxx>
77 #include <docuno.hxx>
78 #include <scresid.hxx>
79 #include <columniterator.hxx>
80 #include <globalnames.hxx>
81 #include <stringutil.hxx>
82 #include <documentlinkmgr.hxx>
83 #include <tokenarray.hxx>
84 #include <recursionhelper.hxx>
85 
86 #include <memory>
87 #include <utility>
88 
89 using namespace com::sun::star;
90 
91 namespace {
92 
93 sal_uInt16 getScaleValue(SfxStyleSheetBase& rStyle, sal_uInt16 nWhich)
94 {
95  return static_cast<const SfxUInt16Item&>(rStyle.GetItemSet().Get(nWhich)).GetValue();
96 }
97 
98 }
99 
101 {
102  pDocOptions.reset( new ScDocOptions() );
103  pViewOptions.reset( new ScViewOptions() );
104 }
105 
107 {
108  pDocOptions.reset();
109  pViewOptions.reset();
110  pExtDocOptions.reset();
111 }
112 
113 SfxPrinter* ScDocument::GetPrinter(bool bCreateIfNotExist)
114 {
115  if ( !mpPrinter && bCreateIfNotExist )
116  {
117  auto pSet =
118  std::make_unique<SfxItemSet>( *mxPoolHelper->GetDocPool(),
119  svl::Items<SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
120  SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
121  SID_PRINT_SELECTEDSHEET, SID_PRINT_SELECTEDSHEET,
122  SID_SCPRINTOPTIONS, SID_SCPRINTOPTIONS>{} );
123 
124  SfxPrinterChangeFlags nFlags = SfxPrinterChangeFlags::NONE;
125  if (officecfg::Office::Common::Print::Warning::PaperOrientation::get())
126  nFlags |= SfxPrinterChangeFlags::CHG_ORIENTATION;
127  if (officecfg::Office::Common::Print::Warning::PaperSize::get())
128  nFlags |= SfxPrinterChangeFlags::CHG_SIZE;
129  pSet->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, static_cast<int>(nFlags) ) );
130  pSet->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, officecfg::Office::Common::Print::Warning::NotFound::get() ) );
131 
132  mpPrinter = VclPtr<SfxPrinter>::Create( std::move(pSet) );
133  mpPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
134  UpdateDrawPrinter();
135  mpPrinter->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
136  }
137 
138  return mpPrinter;
139 }
140 
141 void ScDocument::SetPrinter( VclPtr<SfxPrinter> const & pNewPrinter )
142 {
143  if ( pNewPrinter == mpPrinter.get() )
144  {
145  // #i6706# SetPrinter is called with the same printer again if
146  // the JobSetup has changed. In that case just call UpdateDrawPrinter
147  // (SetRefDevice for drawing layer) because of changed text sizes.
148  UpdateDrawPrinter();
149  }
150  else
151  {
152  ScopedVclPtr<SfxPrinter> xKeepAlive( mpPrinter );
153  mpPrinter = pNewPrinter;
154  UpdateDrawPrinter();
155  mpPrinter->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
156  }
157  InvalidateTextWidth(nullptr, nullptr, false); // in both cases
158 }
159 
161 {
162  if ( !mpPrinter ) GetPrinter(); // this sets mpPrinter
163  OSL_ENSURE( mpPrinter, "Error in printer creation :-/" );
164 
165  if ( !mpPrinter )
166  return;
167 
168  SfxItemSet aOptSet( mpPrinter->GetOptions() );
169 
170  SfxPrinterChangeFlags nFlags = SfxPrinterChangeFlags::NONE;
171  if (officecfg::Office::Common::Print::Warning::PaperOrientation::get())
172  nFlags |= SfxPrinterChangeFlags::CHG_ORIENTATION;
173  if (officecfg::Office::Common::Print::Warning::PaperSize::get())
174  nFlags |= SfxPrinterChangeFlags::CHG_SIZE;
175  aOptSet.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, static_cast<int>(nFlags) ) );
176  aOptSet.Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, officecfg::Office::Common::Print::Warning::NotFound::get() ) );
177 
178  mpPrinter->SetOptions( aOptSet );
179 }
180 
182 {
183  if (!mpVirtualDevice_100th_mm)
184  {
185 #ifdef IOS
186  mpVirtualDevice_100th_mm = VclPtr<VirtualDevice>::Create(DeviceFormat::GRAYSCALE);
187 #else
188  mpVirtualDevice_100th_mm = VclPtr<VirtualDevice>::Create(DeviceFormat::BITMASK);
189 #endif
190  mpVirtualDevice_100th_mm->SetReferenceDevice(VirtualDevice::RefDevMode::MSO1);
191  MapMode aMapMode( mpVirtualDevice_100th_mm->GetMapMode() );
192  aMapMode.SetMapUnit( MapUnit::Map100thMM );
193  mpVirtualDevice_100th_mm->SetMapMode( aMapMode );
194  }
195  return mpVirtualDevice_100th_mm;
196 }
197 
199 {
200  // Create printer like ref device, see Writer...
201  OutputDevice* pRefDevice = nullptr;
202  if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
203  pRefDevice = GetPrinter();
204  else
205  pRefDevice = GetVirtualDevice_100th_mm();
206  return pRefDevice;
207 }
208 
210  const SfxItemSet& rChanges )
211 {
212  SfxItemSet& rSet = rStyleSheet.GetItemSet();
213 
214  switch ( rStyleSheet.GetFamily() )
215  {
216  case SfxStyleFamily::Page:
217  {
218  const sal_uInt16 nOldScale = getScaleValue(rStyleSheet, ATTR_PAGE_SCALE);
219  const sal_uInt16 nOldScaleToPages = getScaleValue(rStyleSheet, ATTR_PAGE_SCALETOPAGES);
220  rSet.Put( rChanges );
221  const sal_uInt16 nNewScale = getScaleValue(rStyleSheet, ATTR_PAGE_SCALE);
222  const sal_uInt16 nNewScaleToPages = getScaleValue(rStyleSheet, ATTR_PAGE_SCALETOPAGES);
223 
224  if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
225  InvalidateTextWidth( rStyleSheet.GetName() );
226 
228  {
229  const SfxPoolItem *pItem = nullptr;
230  if( rChanges.GetItemState(ATTR_WRITINGDIR, true, &pItem ) == SfxItemState::SET )
232  }
233  }
234  break;
235 
236  case SfxStyleFamily::Para:
237  {
238  bool bNumFormatChanged;
239  if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
240  rSet, rChanges ) )
241  InvalidateTextWidth( nullptr, nullptr, bNumFormatChanged );
242 
243  for (SCTAB nTab=0; nTab<=MAXTAB; ++nTab)
244  if (maTabs[nTab])
245  maTabs[nTab]->SetStreamValid( false );
246 
247  sal_uLong nOldFormat =
248  rSet.Get( ATTR_VALUE_FORMAT ).GetValue();
249  sal_uLong nNewFormat =
250  rChanges.Get( ATTR_VALUE_FORMAT ).GetValue();
251  LanguageType eNewLang, eOldLang;
252  eNewLang = eOldLang = LANGUAGE_DONTKNOW;
253  if ( nNewFormat != nOldFormat )
254  {
255  SvNumberFormatter* pFormatter = GetFormatTable();
256  eOldLang = pFormatter->GetEntry( nOldFormat )->GetLanguage();
257  eNewLang = pFormatter->GetEntry( nNewFormat )->GetLanguage();
258  }
259 
260  // Explanation to Items in rChanges:
261  // Set Item - take over change
262  // Dontcare - Set Default
263  // Default - No change
264  // ("no change" is not possible with PutExtended, thus the loop)
265  for (sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++)
266  {
267  const SfxPoolItem* pItem;
268  SfxItemState eState = rChanges.GetItemState( nWhich, false, &pItem );
269  if ( eState == SfxItemState::SET )
270  rSet.Put( *pItem );
271  else if ( eState == SfxItemState::DONTCARE )
272  rSet.ClearItem( nWhich );
273  // when Default nothing
274  }
275 
276  if ( eNewLang != eOldLang )
277  rSet.Put(
278  SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
279  }
280  break;
281  default:
282  {
283  // added to avoid warnings
284  }
285  }
286 }
287 
289 {
290  // number format exchange list has to be handled here, too
291  NumFmtMergeHandler aNumFmtMergeHdl(*this, rSrcDoc);
292  mxPoolHelper->GetStylePool()->CopyStdStylesFrom( rSrcDoc.mxPoolHelper->GetStylePool() );
293 }
294 
295 void ScDocument::InvalidateTextWidth( std::u16string_view rStyleName )
296 {
297  const SCTAB nCount = GetTableCount();
298  for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
299  if ( maTabs[i]->GetPageStyle() == rStyleName )
300  InvalidateTextWidth( i );
301 }
302 
304 {
305  ScAddress aAdrFrom( 0, 0, nTab );
306  ScAddress aAdrTo ( MaxCol(), MaxRow(), nTab );
307  InvalidateTextWidth( &aAdrFrom, &aAdrTo, false );
308 }
309 
310 bool ScDocument::IsPageStyleInUse( std::u16string_view rStrPageStyle, SCTAB* pInTab )
311 {
312  bool bInUse = false;
313  const SCTAB nCount = GetTableCount();
314  SCTAB i;
315 
316  for ( i = 0; !bInUse && i < nCount && maTabs[i]; i++ )
317  bInUse = ( maTabs[i]->GetPageStyle() == rStrPageStyle );
318 
319  if ( pInTab )
320  *pInTab = i-1;
321 
322  return bInUse;
323 }
324 
325 bool ScDocument::RemovePageStyleInUse( std::u16string_view rStyle )
326 {
327  bool bWasInUse = false;
328  const SCTAB nCount = GetTableCount();
329 
330  for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
331  if ( maTabs[i]->GetPageStyle() == rStyle )
332  {
333  bWasInUse = true;
334  maTabs[i]->SetPageStyle( ScResId(STR_STYLENAME_STANDARD) );
335  }
336 
337  return bWasInUse;
338 }
339 
340 bool ScDocument::RenamePageStyleInUse( std::u16string_view rOld, const OUString& rNew )
341 {
342  bool bWasInUse = false;
343  const SCTAB nCount = GetTableCount();
344 
345  for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
346  if ( maTabs[i]->GetPageStyle() == rOld )
347  {
348  bWasInUse = true;
349  maTabs[i]->SetPageStyle( rNew );
350  }
351 
352  return bWasInUse;
353 }
354 
356 {
357  EEHorizontalTextDirection eRet = EEHorizontalTextDirection::Default;
358 
359  OUString aStyleName = GetPageStyle( nTab );
360  SfxStyleSheetBase* pStyle = mxPoolHelper->GetStylePool()->Find( aStyleName, SfxStyleFamily::Page );
361  if ( pStyle )
362  {
363  SfxItemSet& rStyleSet = pStyle->GetItemSet();
364  SvxFrameDirection eDirection =
365  rStyleSet.Get( ATTR_WRITINGDIR ).GetValue();
366 
367  if ( eDirection == SvxFrameDirection::Horizontal_LR_TB )
368  eRet = EEHorizontalTextDirection::L2R;
369  else if ( eDirection == SvxFrameDirection::Horizontal_RL_TB )
370  eRet = EEHorizontalTextDirection::R2L;
371  // else (invalid for EditEngine): keep "default"
372  }
373 
374  return eRet;
375 }
376 
378 {
379  if (!mpMacroMgr)
380  mpMacroMgr.reset(new ScMacroManager(*this));
381  return mpMacroMgr.get();
382 }
383 
385  ScMatrix& rMat, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, svl::SharedStringPool* pPool ) const
386 {
387  const ScTable* pTab = FetchTable(nTab);
388  if (!pTab)
389  return;
390 
391  if (nCol1 > nCol2 || nRow1 > nRow2)
392  return;
393 
394  SCSIZE nC, nR;
395  rMat.GetDimensions(nC, nR);
396  if (static_cast<SCROW>(nR) != nRow2 - nRow1 + 1 || static_cast<SCCOL>(nC) != nCol2 - nCol1 + 1)
397  return;
398 
399  pTab->FillMatrix(rMat, nCol1, nRow1, nCol2, nRow2, pPool);
400 }
401 
402 void ScDocument::SetFormulaResults( const ScAddress& rTopPos, const double* pResults, size_t nLen )
403 {
404  ScTable* pTab = FetchTable(rTopPos.Tab());
405  if (!pTab)
406  return;
407 
408  pTab->SetFormulaResults(rTopPos.Col(), rTopPos.Row(), pResults, nLen);
409 }
410 
411 void ScDocument::CalculateInColumnInThread( ScInterpreterContext& rContext, const ScRange& rCalcRange, unsigned nThisThread, unsigned nThreadsTotal)
412 {
413  ScTable* pTab = FetchTable(rCalcRange.aStart.Tab());
414  if (!pTab)
415  return;
416 
417  assert(IsThreadedGroupCalcInProgress());
418 
419  maThreadSpecific.pContext = &rContext;
420  pTab->CalculateInColumnInThread(rContext, rCalcRange.aStart.Col(), rCalcRange.aEnd.Col(), rCalcRange.aStart.Row(), rCalcRange.aEnd.Row(), nThisThread, nThreadsTotal);
421 
422  assert(IsThreadedGroupCalcInProgress());
423  maThreadSpecific.pContext = nullptr;
424  // If any of the thread_local data would cause problems if they stay around for too long
425  // (and e.g. outlive the ScDocument), clean them up here, they cannot be cleaned up
426  // later from the main thread.
427  if(maThreadSpecific.xRecursionHelper)
428  maThreadSpecific.xRecursionHelper->Clear();
429 }
430 
431 void ScDocument::HandleStuffAfterParallelCalculation( SCCOL nColStart, SCCOL nColEnd, SCROW nRow, size_t nLen, SCTAB nTab, ScInterpreter* pInterpreter )
432 {
433  assert(!IsThreadedGroupCalcInProgress());
434  for( const DelayedSetNumberFormat& data : GetNonThreadedContext().maDelayedSetNumberFormat)
435  SetNumberFormat( ScAddress( data.mCol, data.mRow, nTab ), data.mnNumberFormat );
436  GetNonThreadedContext().maDelayedSetNumberFormat.clear();
437 
438  ScTable* pTab = FetchTable(nTab);
439  if (!pTab)
440  return;
441 
442  pTab->HandleStuffAfterParallelCalculation(nColStart, nColEnd, nRow, nLen, pInterpreter);
443 }
444 
445 void ScDocument::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
446  bool bNumFormatChanged )
447 {
448  bool bBroadcast = (bNumFormatChanged && GetDocOptions().IsCalcAsShown() && !IsImportingXML() && !IsClipboard());
449  if ( pAdrFrom && !pAdrTo )
450  {
451  const SCTAB nTab = pAdrFrom->Tab();
452 
453  if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
454  maTabs[nTab]->InvalidateTextWidth( pAdrFrom, nullptr, bNumFormatChanged, bBroadcast );
455  }
456  else
457  {
458  const SCTAB nTabStart = pAdrFrom ? pAdrFrom->Tab() : 0;
459  const SCTAB nTabEnd = pAdrTo ? pAdrTo->Tab() : MAXTAB;
460 
461  for ( SCTAB nTab=nTabStart; nTab<=nTabEnd && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
462  if ( maTabs[nTab] )
463  maTabs[nTab]->InvalidateTextWidth( pAdrFrom, pAdrTo, bNumFormatChanged, bBroadcast );
464  }
465 }
466 
467 #define CALCMAX 1000 // Calculations
468 
469 namespace {
470 
471 class IdleCalcTextWidthScope : public TaskStopwatch
472 {
473  ScDocument& mrDoc;
474  ScAddress& mrCalcPos;
475  MapMode maOldMapMode;
476  ScStyleSheetPool* mpStylePool;
477  bool mbNeedMore;
478  bool mbProgress;
479 
480 public:
481  IdleCalcTextWidthScope(ScDocument& rDoc, ScAddress& rCalcPos) :
482  mrDoc(rDoc),
483  mrCalcPos(rCalcPos),
484  mpStylePool(rDoc.GetStyleSheetPool()),
485  mbNeedMore(false),
486  mbProgress(false)
487  {
488  mrDoc.EnableIdle(false);
489  }
490 
491  ~IdleCalcTextWidthScope() COVERITY_NOEXCEPT_FALSE
492  {
493  SfxPrinter* pDev = mrDoc.GetPrinter();
494  if (pDev)
495  pDev->SetMapMode(maOldMapMode);
496 
497  if (mbProgress)
499 
500  mrDoc.EnableIdle(true);
501  }
502 
503  SCTAB Tab() const { return mrCalcPos.Tab(); }
504  SCCOL Col() const { return mrCalcPos.Col(); }
505  SCROW Row() const { return mrCalcPos.Row(); }
506 
507  void setTab(SCTAB nTab) { mrCalcPos.SetTab(nTab); }
508  void setCol(SCCOL nCol) { mrCalcPos.SetCol(nCol); }
509  void setRow(SCROW nRow) { mrCalcPos.SetRow(nRow); }
510 
511  void incTab() { mrCalcPos.IncTab(); }
512  void incCol(SCCOL nInc) { mrCalcPos.IncCol(nInc); }
513 
514  void setOldMapMode(const MapMode& rOldMapMode) { maOldMapMode = rOldMapMode; }
515 
516  void setNeedMore(bool b) { mbNeedMore = b; }
517  bool getNeedMore() const { return mbNeedMore; }
518 
519  void createProgressBar()
520  {
522  mbProgress = true;
523  }
524 
525  bool hasProgressBar() const { return mbProgress; }
526 
527  ScStyleSheetPool* getStylePool() { return mpStylePool; }
528 };
529 
530 }
531 
532 bool ScDocument::IdleCalcTextWidth() // true = try next again
533 {
534  // #i75610# if a printer hasn't been set or created yet, don't create one for this
535  if (!mbIdleEnabled || IsInLinkUpdate() || GetPrinter(false) == nullptr)
536  return false;
537 
538  IdleCalcTextWidthScope aScope(*this, aCurTextWidthCalcPos);
539 
540  if (!ValidRow(aScope.Row()))
541  {
542  aScope.setRow(0);
543  aScope.incCol(-1);
544  }
545 
546  if (aScope.Col() < 0)
547  {
548  aScope.setCol(MaxCol());
549  aScope.incTab();
550  }
551 
552  if (!ValidTab(aScope.Tab()) || aScope.Tab() >= static_cast<SCTAB>(maTabs.size()) || !maTabs[aScope.Tab()])
553  aScope.setTab(0);
554 
555  ScTable* pTab = maTabs[aScope.Tab()].get();
556  ScStyleSheet* pStyle = static_cast<ScStyleSheet*>(aScope.getStylePool()->Find(pTab->aPageStyle, SfxStyleFamily::Page));
557  OSL_ENSURE( pStyle, "Missing StyleSheet :-/" );
558 
559  if (!pStyle || getScaleValue(*pStyle, ATTR_PAGE_SCALETOPAGES) == 0)
560  {
561  // Move to the next sheet as the current one has scale-to-pages set,
562  // and bail out.
563  aScope.incTab();
564  return false;
565  }
566 
567  sal_uInt16 nZoom = getScaleValue(*pStyle, ATTR_PAGE_SCALE);
568  Fraction aZoomFract(nZoom, 100);
569 
570  aScope.setCol(pTab->ClampToAllocatedColumns(aScope.Col()));
571  // Start at specified cell position (nCol, nRow, nTab).
572  ScColumn* pCol = &pTab->aCol[aScope.Col()];
573  std::unique_ptr<ScColumnTextWidthIterator> pColIter(new ScColumnTextWidthIterator(*this, *pCol, aScope.Row(), MaxRow()));
574 
575  OutputDevice* pDev = nullptr;
576  sal_uInt16 nRestart = 0;
577  sal_uInt16 nCount = 0;
578  while ( (nZoom > 0) && (nCount < CALCMAX) && (nRestart < 2) )
579  {
580  if (pColIter->hasCell())
581  {
582  // More cell in this column.
583  SCROW nRow = pColIter->getPos();
584  aScope.setRow(nRow);
585 
586  if (pColIter->getValue() == TEXTWIDTH_DIRTY)
587  {
588  // Calculate text width for this cell.
589  double nPPTX = 0.0;
590  double nPPTY = 0.0;
591  if (!pDev)
592  {
593  pDev = GetPrinter();
594  aScope.setOldMapMode(pDev->GetMapMode());
595  pDev->SetMapMode(MapMode(MapUnit::MapPixel)); // Important for GetNeededSize
596 
597  Point aPix1000 = pDev->LogicToPixel(Point(1000,1000), MapMode(MapUnit::MapTwip));
598  nPPTX = aPix1000.X() / 1000.0;
599  nPPTY = aPix1000.Y() / 1000.0;
600  }
601 
602  if (!aScope.hasProgressBar() && pCol->IsFormulaDirty(nRow))
603  aScope.createProgressBar();
604 
605  sal_uInt16 nNewWidth = static_cast<sal_uInt16>(GetNeededSize(
606  aScope.Col(), aScope.Row(), aScope.Tab(),
607  pDev, nPPTX, nPPTY, aZoomFract,aZoomFract, true, true)); // bTotalSize
608 
609  pColIter->setValue(nNewWidth);
610  aScope.setNeedMore(true);
611  }
612  pColIter->next();
613  }
614  else
615  {
616  // No more cell in this column. Move to the left column and start at row 0.
617 
618  bool bNewTab = false;
619 
620  aScope.setRow(0);
621  aScope.incCol(-1);
622 
623  if (aScope.Col() < 0)
624  {
625  // No more column to the left. Move to the right-most column of the next sheet.
626  aScope.setCol(MaxCol());
627  aScope.incTab();
628  bNewTab = true;
629  }
630 
631  if (!ValidTab(aScope.Tab()) || aScope.Tab() >= static_cast<SCTAB>(maTabs.size()) || !maTabs[aScope.Tab()] )
632  {
633  // Sheet doesn't exist at specified sheet position. Restart at sheet 0.
634  aScope.setTab(0);
635  nRestart++;
636  bNewTab = true;
637  }
638 
639  if ( nRestart < 2 )
640  {
641  if ( bNewTab )
642  {
643  pTab = maTabs[aScope.Tab()].get();
644  aScope.setCol(pTab->ClampToAllocatedColumns(aScope.Col()));
645  pStyle = static_cast<ScStyleSheet*>(aScope.getStylePool()->Find(
646  pTab->aPageStyle, SfxStyleFamily::Page));
647 
648  if ( pStyle )
649  {
650  // Check if the scale-to-pages setting is set. If
651  // set, we exit the loop. If not, get the page
652  // scale factor of the new sheet.
653  if (getScaleValue(*pStyle, ATTR_PAGE_SCALETOPAGES) == 0)
654  {
655  nZoom = getScaleValue(*pStyle, ATTR_PAGE_SCALE);
656  aZoomFract = Fraction(nZoom, 100);
657  }
658  else
659  nZoom = 0;
660  }
661  else
662  {
663  OSL_FAIL( "Missing StyleSheet :-/" );
664  }
665  }
666 
667  if ( nZoom > 0 )
668  {
669  pCol = &pTab->aCol[aScope.Col()];
670  pColIter.reset(new ScColumnTextWidthIterator(*this, *pCol, aScope.Row(), MaxRow()));
671  }
672  else
673  {
674  aScope.incTab(); // Move to the next sheet as the current one has scale-to-pages set.
675  return false;
676  }
677  }
678  }
679 
680  ++nCount;
681 
682  if (!aScope.continueIter())
683  break;
684  }
685 
686  return aScope.getNeedMore();
687 }
688 
689 void ScDocument::RepaintRange( const ScRange& rRange )
690 {
691  if ( bIsVisible && mpShell )
692  {
693  ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>( mpShell->GetModel() );
694  if ( pModel )
695  pModel->RepaintRange( rRange ); // locked repaints are checked there
696  }
697 }
698 
700 {
701  if ( bIsVisible && mpShell )
702  {
703  ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>( mpShell->GetModel() );
704  if ( pModel )
705  pModel->RepaintRange( rRange ); // locked repaints are checked there
706  }
707 }
708 
709 void ScDocument::SaveDdeLinks(SvStream& rStream) const
710 {
711  // when 4.0-Export, remove all with mode != DEFAULT
712  bool bExport40 = ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_40 );
713 
714  const ::sfx2::SvBaseLinks& rLinks = GetLinkManager()->GetLinks();
715  sal_uInt16 nCount = rLinks.size();
716 
717  // Count them first
718 
719  sal_uInt16 nDdeCount = 0;
720  sal_uInt16 i;
721  for (i=0; i<nCount; i++)
722  {
723  ::sfx2::SvBaseLink* pBase = rLinks[i].get();
724  if (ScDdeLink* pLink = dynamic_cast<ScDdeLink*>(pBase))
725  if ( !bExport40 || pLink->GetMode() == SC_DDE_DEFAULT )
726  ++nDdeCount;
727  }
728 
729  // Header
730 
731  ScMultipleWriteHeader aHdr( rStream );
732  rStream.WriteUInt16( nDdeCount );
733 
734  // Save links
735 
736  for (i=0; i<nCount; i++)
737  {
738  ::sfx2::SvBaseLink* pBase = rLinks[i].get();
739  if (ScDdeLink* pLink = dynamic_cast<ScDdeLink*>(pBase))
740  {
741  if ( !bExport40 || pLink->GetMode() == SC_DDE_DEFAULT )
742  pLink->Store( rStream, aHdr );
743  }
744  }
745 }
746 
748 {
749  sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(bAutoCalc);
750  if (!pMgr)
751  return;
752 
753  ScMultipleReadHeader aHdr( rStream );
754 
755  sal_uInt16 nCount(0);
756  rStream.ReadUInt16( nCount );
757 
758  const rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
759  const size_t nMinStringSize = eCharSet == RTL_TEXTENCODING_UNICODE ? sizeof(sal_uInt32) : sizeof(sal_uInt16);
760  const size_t nMinRecordSize = 1 + nMinStringSize*3;
761  const size_t nMaxRecords = rStream.remainingSize() / nMinRecordSize;
762  if (nCount > nMaxRecords)
763  {
764  SAL_WARN("sc", "Parsing error: " << nMaxRecords <<
765  " max possible entries, but " << nCount << " claimed, truncating");
766  nCount = nMaxRecords;
767  }
768 
769  for (sal_uInt16 i=0; i<nCount; ++i)
770  {
771  ScDdeLink* pLink = new ScDdeLink( *this, rStream, aHdr );
772  pMgr->InsertDDELink(pLink, pLink->GetAppl(), pLink->GetTopic(), pLink->GetItem());
773  }
774 }
775 
777 {
778  // called from TableLink and AreaLink
779 
780  OSL_ENSURE( bInLinkUpdate != bSet, "SetInLinkUpdate twice" );
781  bInLinkUpdate = bSet;
782 }
783 
785 {
786  return bInLinkUpdate || IsInDdeLinkUpdate();
787 }
788 
790 {
791  if (!pExternalRefMgr)
792  return;
793 
794  sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(bAutoCalc);
795  if (!pMgr)
796  return;
797 
798  const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
799  sal_uInt16 nCount = rLinks.size();
800 
801  bool bAny = false;
802 
803  // Collect all the external ref links first.
804  std::vector<ScExternalRefLink*> aRefLinks;
805  for (sal_uInt16 i = 0; i < nCount; ++i)
806  {
807  ::sfx2::SvBaseLink* pBase = rLinks[i].get();
808  ScExternalRefLink* pRefLink = dynamic_cast<ScExternalRefLink*>(pBase);
809  if (pRefLink)
810  aRefLinks.push_back(pRefLink);
811  }
812 
813  weld::WaitObject aWaitSwitch(pWin);
814 
815  pExternalRefMgr->enableDocTimer(false);
816  ScProgress aProgress(GetDocumentShell(), ScResId(SCSTR_UPDATE_EXTDOCS), aRefLinks.size(), true);
817  for (size_t i = 0, n = aRefLinks.size(); i < n; ++i)
818  {
819  aProgress.SetState(i+1);
820 
821  ScExternalRefLink* pRefLink = aRefLinks[i];
822  if (pRefLink->Update())
823  {
824  bAny = true;
825  continue;
826  }
827 
828  // Update failed. Notify the user.
829 
830  OUString aFile;
831  sfx2::LinkManager::GetDisplayNames(pRefLink, nullptr, &aFile);
832  // Decode encoded URL for display friendliness.
835 
836  OUString sMessage = ScResId(SCSTR_EXTDOC_NOT_LOADED) +
837  "\n\n" +
838  aFile;
839  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pWin,
840  VclMessageType::Warning, VclButtonsType::Ok,
841  sMessage));
842  xBox->run();
843  }
844 
845  pExternalRefMgr->enableDocTimer(true);
846 
847  if (!bAny)
848  return;
849 
850  TrackFormulas();
851  mpShell->Broadcast( SfxHint(SfxHintId::ScDataChanged) );
852 
853  // #i101960# set document modified, as in TrackTimeHdl for DDE links
854  if (!mpShell->IsModified())
855  {
856  mpShell->SetModified();
857  SfxBindings* pBindings = GetViewBindings();
858  if (pBindings)
859  {
860  pBindings->Invalidate( SID_SAVEDOC );
861  pBindings->Invalidate( SID_DOC_MODIFIED );
862  }
863  }
864 }
865 
866 void ScDocument::CopyDdeLinks( ScDocument& rDestDoc ) const
867 {
868  if (bIsClip) // Create from Stream
869  {
870  if (pClipData)
871  {
872  pClipData->Seek(0);
873  rDestDoc.LoadDdeLinks(*pClipData);
874  }
875 
876  return;
877  }
878 
879  const sfx2::LinkManager* pMgr = GetDocLinkManager().getExistingLinkManager();
880  if (!pMgr)
881  return;
882 
883  sfx2::LinkManager* pDestMgr = rDestDoc.GetDocLinkManager().getLinkManager(rDestDoc.bAutoCalc);
884  if (!pDestMgr)
885  return;
886 
887  const sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
888  for (const auto & rLink : rLinks)
889  {
890  const sfx2::SvBaseLink* pBase = rLink.get();
891  if (const ScDdeLink* p = dynamic_cast<const ScDdeLink*>(pBase))
892  {
893  ScDdeLink* pNew = new ScDdeLink(rDestDoc, *p);
894  pDestMgr->InsertDDELink(
895  pNew, pNew->GetAppl(), pNew->GetTopic(), pNew->GetItem());
896  }
897  }
898 }
899 
900 namespace {
901 
906 ScDdeLink* lclGetDdeLink(
907  const sfx2::LinkManager* pLinkManager,
908  std::u16string_view rAppl, std::u16string_view rTopic, std::u16string_view rItem, sal_uInt8 nMode,
909  size_t* pnDdePos = nullptr )
910 {
911  if( pLinkManager )
912  {
913  const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
914  size_t nCount = rLinks.size();
915  if( pnDdePos ) *pnDdePos = 0;
916  for( size_t nIndex = 0; nIndex < nCount; ++nIndex )
917  {
918  ::sfx2::SvBaseLink* pLink = rLinks[ nIndex ].get();
919  if( ScDdeLink* pDdeLink = dynamic_cast<ScDdeLink*>( pLink ) )
920  {
921  if( (pDdeLink->GetAppl() == rAppl) &&
922  (pDdeLink->GetTopic() == rTopic) &&
923  (pDdeLink->GetItem() == rItem) &&
924  ((nMode == SC_DDE_IGNOREMODE) || (nMode == pDdeLink->GetMode())) )
925  return pDdeLink;
926  if( pnDdePos ) ++*pnDdePos;
927  }
928  }
929  }
930  return nullptr;
931 }
932 
936 ScDdeLink* lclGetDdeLink( const sfx2::LinkManager* pLinkManager, size_t nDdePos )
937 {
938  if( pLinkManager )
939  {
940  const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
941  size_t nCount = rLinks.size();
942  size_t nDdeIndex = 0; // counts only the DDE links
943  for( size_t nIndex = 0; nIndex < nCount; ++nIndex )
944  {
945  ::sfx2::SvBaseLink* pLink = rLinks[ nIndex ].get();
946  if( ScDdeLink* pDdeLink = dynamic_cast<ScDdeLink*>( pLink ) )
947  {
948  if( nDdeIndex == nDdePos )
949  return pDdeLink;
950  ++nDdeIndex;
951  }
952  }
953  }
954  return nullptr;
955 }
956 
957 } // namespace
958 
959 bool ScDocument::FindDdeLink( std::u16string_view rAppl, std::u16string_view rTopic, std::u16string_view rItem,
960  sal_uInt8 nMode, size_t& rnDdePos )
961 {
962  return lclGetDdeLink( GetLinkManager(), rAppl, rTopic, rItem, nMode, &rnDdePos ) != nullptr;
963 }
964 
965 bool ScDocument::GetDdeLinkData( size_t nDdePos, OUString& rAppl, OUString& rTopic, OUString& rItem ) const
966 {
967  if( const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
968  {
969  rAppl = pDdeLink->GetAppl();
970  rTopic = pDdeLink->GetTopic();
971  rItem = pDdeLink->GetItem();
972  return true;
973  }
974  return false;
975 }
976 
977 bool ScDocument::GetDdeLinkMode( size_t nDdePos, sal_uInt8& rnMode ) const
978 {
979  if( const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
980  {
981  rnMode = pDdeLink->GetMode();
982  return true;
983  }
984  return false;
985 }
986 
987 const ScMatrix* ScDocument::GetDdeLinkResultMatrix( size_t nDdePos ) const
988 {
989  const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos );
990  return pDdeLink ? pDdeLink->GetResult() : nullptr;
991 }
992 
993 bool ScDocument::CreateDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem, sal_uInt8 nMode, const ScMatrixRef& pResults )
994 {
995  /* Create a DDE link without updating it (i.e. for Excel import), to prevent
996  unwanted connections. First try to find existing link. Set result array
997  on existing and new links. */
998  //TODO: store DDE links additionally at document (for efficiency)?
999  OSL_ENSURE( nMode != SC_DDE_IGNOREMODE, "ScDocument::CreateDdeLink - SC_DDE_IGNOREMODE not allowed here" );
1000 
1001  sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(bAutoCalc);
1002  if (!pMgr)
1003  return false;
1004 
1005  if (nMode != SC_DDE_IGNOREMODE)
1006  {
1007  ScDdeLink* pDdeLink = lclGetDdeLink(pMgr, rAppl, rTopic, rItem, nMode);
1008  if( !pDdeLink )
1009  {
1010  // create a new DDE link, but without TryUpdate
1011  pDdeLink = new ScDdeLink( *this, rAppl, rTopic, rItem, nMode );
1012  pMgr->InsertDDELink(pDdeLink, rAppl, rTopic, rItem);
1013  }
1014 
1015  // insert link results
1016  if( pResults )
1017  pDdeLink->SetResult( pResults );
1018 
1019  return true;
1020  }
1021  return false;
1022 }
1023 
1024 bool ScDocument::SetDdeLinkResultMatrix( size_t nDdePos, const ScMatrixRef& pResults )
1025 {
1026  if( ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
1027  {
1028  pDdeLink->SetResult( pResults );
1029  return true;
1030  }
1031  return false;
1032 }
1033 
1035 {
1036  const sfx2::LinkManager* pMgr = GetDocLinkManager().getExistingLinkManager();
1037  if (!pMgr)
1038  return false;
1039 
1040  const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1041  sal_uInt16 nCount = rLinks.size();
1042  for (sal_uInt16 i=0; i<nCount; i++)
1043  if (nullptr != dynamic_cast<const ScAreaLink* >(rLinks[i].get()))
1044  return true;
1045 
1046  return false;
1047 }
1048 
1050 {
1051  sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(false);
1052  if (!pMgr)
1053  return;
1054 
1055  const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1056  for (const auto & rLink : rLinks)
1057  {
1058  ::sfx2::SvBaseLink* pBase = rLink.get();
1059  if (dynamic_cast<const ScAreaLink*>( pBase) != nullptr)
1060  pBase->Update();
1061  }
1062 }
1063 
1065 {
1066  sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(false);
1067  if (!pMgr)
1068  return;
1069 
1070  const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1071  sfx2::SvBaseLinks::size_type nPos = 0;
1072  while ( nPos < rLinks.size() )
1073  {
1074  const ::sfx2::SvBaseLink* pBase = rLinks[nPos].get();
1075  const ScAreaLink* pLink = dynamic_cast<const ScAreaLink*>(pBase);
1076  if (pLink && pLink->GetDestArea().aStart.Tab() == nTab)
1077  pMgr->Remove(nPos);
1078  else
1079  ++nPos;
1080  }
1081 }
1082 
1084  const ScRange& rRange, SCCOL nDx, SCROW nDy, SCTAB nDz )
1085 {
1086  sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(false);
1087  if (!pMgr)
1088  return;
1089 
1090  bool bAnyUpdate = false;
1091 
1092  const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1093  sal_uInt16 nCount = rLinks.size();
1094  for (sal_uInt16 i=0; i<nCount; i++)
1095  {
1096  ::sfx2::SvBaseLink* pBase = rLinks[i].get();
1097  if (ScAreaLink* pLink = dynamic_cast<ScAreaLink*>(pBase))
1098  {
1099  ScRange aOutRange = pLink->GetDestArea();
1100 
1101  SCCOL nCol1 = aOutRange.aStart.Col();
1102  SCROW nRow1 = aOutRange.aStart.Row();
1103  SCTAB nTab1 = aOutRange.aStart.Tab();
1104  SCCOL nCol2 = aOutRange.aEnd.Col();
1105  SCROW nRow2 = aOutRange.aEnd.Row();
1106  SCTAB nTab2 = aOutRange.aEnd.Tab();
1107 
1108  ScRefUpdateRes eRes =
1109  ScRefUpdate::Update( this, eUpdateRefMode,
1110  rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
1111  rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
1112  nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1113  if ( eRes != UR_NOTHING )
1114  {
1115  pLink->SetDestArea( ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ) );
1116  bAnyUpdate = true;
1117  }
1118  }
1119  }
1120 
1121  if ( !bAnyUpdate )
1122  return;
1123 
1124  // #i52120# Look for duplicates (after updating all positions).
1125  // If several links start at the same cell, the one with the lower index is removed
1126  // (file format specifies only one link definition for a cell).
1127 
1128  sal_uInt16 nFirstIndex = 0;
1129  while ( nFirstIndex < nCount )
1130  {
1131  bool bFound = false;
1132  ::sfx2::SvBaseLink* pFirst = rLinks[nFirstIndex].get();
1133  if (ScAreaLink* pFirstLink = dynamic_cast<ScAreaLink*>(pFirst))
1134  {
1135  ScAddress aFirstPos = pFirstLink->GetDestArea().aStart;
1136  for ( sal_uInt16 nSecondIndex = nFirstIndex + 1; nSecondIndex < nCount && !bFound; ++nSecondIndex )
1137  {
1138  ::sfx2::SvBaseLink* pSecond = rLinks[nSecondIndex].get();
1139  ScAreaLink* pSecondLink = dynamic_cast<ScAreaLink*>(pSecond);
1140  if (pSecondLink && pSecondLink->GetDestArea().aStart == aFirstPos)
1141  {
1142  // remove the first link, exit the inner loop, don't increment nFirstIndex
1143  pMgr->Remove(pFirst);
1144  nCount = rLinks.size();
1145  bFound = true;
1146  }
1147  }
1148  }
1149  if (!bFound)
1150  ++nFirstIndex;
1151  }
1152 }
1153 
1155 {
1156  if (HasLinkFormulaNeedingCheck())
1157  return;
1158 
1159  // Prefer RPN over tokenized formula if available.
1160  if (rCode.GetCodeLen())
1161  {
1162  if (rCode.HasOpCodeRPN(ocDde) || rCode.HasOpCodeRPN(ocWebservice))
1163  SetLinkFormulaNeedingCheck(true);
1164  }
1165  else if (rCode.GetLen())
1166  {
1167  if (rCode.HasOpCode(ocDde) || rCode.HasOpCode(ocWebservice))
1168  SetLinkFormulaNeedingCheck(true);
1169  }
1170  else
1171  {
1172  // Possible with named expression without expression like Excel
1173  // internal print ranges, obscure user define names, ... formula error
1174  // cells without formula ...
1175  SAL_WARN("sc.core","ScDocument::CheckLinkFormulaNeedingCheck - called with empty ScTokenArray");
1176  }
1177 }
1178 
1179 // TimerDelays etc.
1181 {
1182  if ( pChartListenerCollection->hasListeners() )
1183  pChartListenerCollection->StartTimer();
1184  if (apTemporaryChartLock)
1185  apTemporaryChartLock->StartOrContinueLocking();
1186 }
1187 
1189 {
1190  // used to invalidate slots after changes to this document
1191 
1192  if ( !mpShell )
1193  return nullptr; // no ObjShell -> no view
1194 
1195  // first check current view
1196  SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1197  if ( pViewFrame && pViewFrame->GetObjectShell() != mpShell ) // wrong document?
1198  pViewFrame = nullptr;
1199 
1200  // otherwise use first view for this doc
1201  if ( !pViewFrame )
1202  pViewFrame = SfxViewFrame::GetFirst( mpShell );
1203 
1204  if (pViewFrame)
1205  return &pViewFrame->GetBindings();
1206  else
1207  return nullptr;
1208 }
1209 
1211 {
1212  OSL_ENSURE( rMultiMark.IsMultiMarked(), "TransliterateText: no selection" );
1213 
1214  utl::TransliterationWrapper aTransliterationWrapper( comphelper::getProcessComponentContext(), nType );
1215  bool bConsiderLanguage = aTransliterationWrapper.needLanguageForTheMode();
1216  LanguageType nLanguage = LANGUAGE_SYSTEM;
1217 
1218  std::unique_ptr<ScEditEngineDefaulter> pEngine; // not using mpEditEngine member because of defaults
1219 
1220  SCTAB nCount = GetTableCount();
1221  for (const SCTAB& nTab : rMultiMark)
1222  {
1223  if (nTab >= nCount)
1224  break;
1225 
1226  if ( maTabs[nTab] )
1227  {
1228  SCCOL nCol = 0;
1229  SCROW nRow = 0;
1230 
1231  bool bFound = rMultiMark.IsCellMarked( nCol, nRow );
1232  if (!bFound)
1233  bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
1234 
1235  while (bFound)
1236  {
1237  ScRefCellValue aCell(*this, ScAddress(nCol, nRow, nTab));
1238 
1239  // fdo#32786 TITLE_CASE/SENTENCE_CASE need the extra handling in EditEngine (loop over words/sentences).
1240  // Still use TransliterationWrapper directly for text cells with other transliteration types,
1241  // for performance reasons.
1242  if (aCell.meType == CELLTYPE_EDIT ||
1243  (aCell.meType == CELLTYPE_STRING &&
1244  ( nType == TransliterationFlags::SENTENCE_CASE || nType == TransliterationFlags::TITLE_CASE)))
1245  {
1246  if (!pEngine)
1247  pEngine.reset(new ScFieldEditEngine(this, GetEnginePool(), GetEditPool()));
1248 
1249  // defaults from cell attributes must be set so right language is used
1250  const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
1251  std::unique_ptr<SfxItemSet> pDefaults(new SfxItemSet( pEngine->GetEmptyItemSet() ));
1252  if ( ScStyleSheet* pPreviewStyle = GetPreviewCellStyle( nCol, nRow, nTab ) )
1253  {
1254  std::unique_ptr<ScPatternAttr> pPreviewPattern(new ScPatternAttr( *pPattern ));
1255  pPreviewPattern->SetStyleSheet(pPreviewStyle);
1256  pPreviewPattern->FillEditItemSet( pDefaults.get() );
1257  }
1258  else
1259  {
1260  SfxItemSet* pFontSet = GetPreviewFont( nCol, nRow, nTab );
1261  pPattern->FillEditItemSet( pDefaults.get(), pFontSet );
1262  }
1263  pEngine->SetDefaults( std::move(pDefaults) );
1264  if (aCell.meType == CELLTYPE_STRING)
1265  pEngine->SetTextCurrentDefaults(aCell.mpString->getString());
1266  else if (aCell.mpEditText)
1267  pEngine->SetTextCurrentDefaults(*aCell.mpEditText);
1268 
1269  pEngine->ClearModifyFlag();
1270 
1271  sal_Int32 nLastPar = pEngine->GetParagraphCount();
1272  if (nLastPar)
1273  --nLastPar;
1274  sal_Int32 nTxtLen = pEngine->GetTextLen(nLastPar);
1275  ESelection aSelAll( 0, 0, nLastPar, nTxtLen );
1276 
1277  pEngine->TransliterateText( aSelAll, nType );
1278 
1279  if ( pEngine->IsModified() )
1280  {
1281  ScEditAttrTester aTester( pEngine.get() );
1282  if ( aTester.NeedsObject() )
1283  {
1284  // remove defaults (paragraph attributes) before creating text object
1285  pEngine->SetDefaults( std::make_unique<SfxItemSet>( pEngine->GetEmptyItemSet() ) );
1286 
1287  // The cell will take ownership of the text object instance.
1288  SetEditText(ScAddress(nCol,nRow,nTab), pEngine->CreateTextObject());
1289  }
1290  else
1291  {
1292  ScSetStringParam aParam;
1293  aParam.setTextInput();
1294  SetString(ScAddress(nCol,nRow,nTab), pEngine->GetText(), &aParam);
1295  }
1296  }
1297  }
1298 
1299  else if (aCell.meType == CELLTYPE_STRING)
1300  {
1301  OUString aOldStr = aCell.mpString->getString();
1302  sal_Int32 nOldLen = aOldStr.getLength();
1303 
1304  if ( bConsiderLanguage )
1305  {
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 :
1310  nLanguage = static_cast<const SvxLanguageItem*>(GetAttr( nCol, nRow, nTab, nWhich ))->GetValue();
1311  }
1312 
1313  uno::Sequence<sal_Int32> aOffsets;
1314  OUString aNewStr = aTransliterationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets );
1315 
1316  if ( aNewStr != aOldStr )
1317  {
1318  ScSetStringParam aParam;
1319  aParam.setTextInput();
1320  SetString(ScAddress(nCol,nRow,nTab), aNewStr, &aParam);
1321  }
1322  }
1323  bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
1324  }
1325  }
1326  }
1327 }
1328 
1329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:112
constexpr double nPPTY
void EnableIdle(bool bDo)
Definition: document.hxx:2121
OUString sMessage
void CalculateInColumnInThread(ScInterpreterContext &rContext, const ScRange &rCalcRange, unsigned nThisThread, unsigned nThreadsTotal)
Definition: documen8.cxx:411
static ScRefUpdateRes Update(const ScDocument *pDoc, UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCCOL nDx, SCROW nDy, SCTAB nDz, SCCOL &theCol1, SCROW &theRow1, SCTAB &theTab1, SCCOL &theCol2, SCROW &theRow2, SCTAB &theTab2)
Definition: refupdat.cxx:188
sal_Int32 nIndex
OUString getString() const
ScAddress aStart
Definition: address.hxx:499
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:42
Store parameters used in the ScDocument::SetString() method.
Definition: stringutil.hxx:34
constexpr TypedWhichId< SvxLanguageItem > ATTR_LANGUAGE_FORMAT(147)
void HandleStuffAfterParallelCalculation(SCCOL nColStart, SCCOL nColEnd, SCROW nRow, size_t nLen, SCTAB nTab, ScInterpreter *pInterpreter)
Definition: documen8.cxx:431
void LoadDdeLinks(SvStream &rStream)
Definition: documen8.cxx:747
SvStream & WriteUInt16(sal_uInt16 nUInt16)
void IncTab(SCTAB nDelta=1)
Definition: address.hxx:307
void SC_DLLPUBLIC SetFormulaResults(const ScAddress &rTopPos, const double *pResults, size_t nLen)
Set an array of numerical formula results to a group of contiguous formula cells. ...
Definition: documen8.cxx:402
SCROW Row() const
Definition: address.hxx:261
void setTextInput()
Call this whenever you need to unconditionally set input as text, no matter what the input is...
Definition: stringutil.cxx:37
constexpr TypedWhichId< SvxLanguageItem > ATTR_CJK_FONT_LANGUAGE(115)
constexpr sal_uInt16 ATTR_PATTERN_START(100)
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
std::string GetValue
sal_Int32 GetVersion() const
void SetInLinkUpdate(bool bSet)
Definition: documen8.cxx:776
SC_DLLPUBLIC void CopyStdStylesFrom(const ScDocument &rSrcDoc)
Definition: documen8.cxx:288
void FillMatrix(ScMatrix &rMat, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, svl::SharedStringPool *pPool=nullptr) const
Definition: documen8.cxx:384
constexpr TypedWhichId< SfxUInt16Item > ATTR_PAGE_SCALETOPAGES(175)
bool IsPageStyleInUse(std::u16string_view rStrPageStyle, SCTAB *pInTab)
Definition: documen8.cxx:310
sal_uIntPtr sal_uLong
constexpr TypedWhichId< SvxLanguageItem > ATTR_FONT_LANGUAGE(110)
const sal_uInt8 SC_DDE_DEFAULT
Definition: document.hxx:291
sal_Int64 n
bool HasOpCode(OpCode) const
#define CALCMAX
Definition: documen8.cxx:467
SC_DLLPUBLIC bool CreateDdeLink(const OUString &rAppl, const OUString &rTopic, const OUString &rItem, sal_uInt8 nMode, const ScMatrixRef &pResults)
Tries to find a DDE link or creates a new, if not extant.
Definition: documen8.cxx:993
void ModifyStyleSheet(SfxStyleSheetBase &rPageStyle, const SfxItemSet &rChanges)
Definition: documen8.cxx:209
void SetFormulaResults(SCCOL nCol, SCROW nRow, const double *pResults, size_t nLen)
Definition: table1.cxx:2551
const MapMode & GetMapMode() const
sal_uInt16 GetCodeLen() const
ScAddress aEnd
Definition: address.hxx:500
SvxFrameDirection
VirtualDevice * GetVirtualDevice_100th_mm()
Definition: documen8.cxx:181
virtual SfxItemSet & GetItemSet()
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:103
void RepaintRange(const ScRange &rRange)
Definition: docuno.cxx:487
void Invalidate(sal_uInt16 nId)
sc::DocumentLinkManager & GetDocLinkManager()
Definition: documen2.cxx:227
SfxStyleFamily GetFamily() const
virtual SfxObjectShell * GetObjectShell() override
void SetPrinter(VclPtr< SfxPrinter > const &pNewPrinter)
Definition: documen8.cxx:141
void SetMapMode()
sfx2::LinkManager * getLinkManager(bool bCreate=true)
void SetString(SwCursor &rCursor, const OUString &rString)
void TransliterateText(const ScMarkData &rMultiMark, TransliterationFlags nType)
Definition: documen8.cxx:1210
SfxPrinter * GetPrinter(bool bCreateIfNotExist=true)
Definition: documen8.cxx:113
void CalculateInColumnInThread(ScInterpreterContext &rContext, SCCOL nColStart, SCCOL nColEnd, SCROW nRowStart, SCROW nRowEnd, unsigned nThisThread, unsigned nThreadsTotal)
Definition: table1.cxx:2559
void RepaintRange(const ScRange &rRange)
Definition: documen8.cxx:689
SC_DLLPUBLIC void CheckLinkFormulaNeedingCheck(const ScTokenArray &rCode)
Check token array and set link check if ocDde/ocWebservice is contained.
Definition: documen8.cxx:1154
const OUString & GetName() const
SfxPrinterChangeFlags
const EditTextObject * mpEditText
Definition: cellvalue.hxx:109
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
void FillMatrix(ScMatrix &rMat, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, svl::SharedStringPool *pPool) const
Definition: table1.cxx:2537
bool IsMultiMarked() const
Definition: markdata.hxx:82
bool SetDdeLinkResultMatrix(size_t nDdePos, const ScMatrixRef &pResults)
Sets a result matrix for the specified DDE link.
Definition: documen8.cxx:1024
int nCount
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
Definition: types.hxx:25
void HandleStuffAfterParallelCalculation(SCCOL nColStart, SCCOL nColEnd, SCROW nRow, size_t nLen, ScInterpreter *pInterpreter)
Definition: table1.cxx:2576
bool RemovePageStyleInUse(std::u16string_view rStrPageStyle)
Definition: documen8.cxx:325
SCTAB Tab() const
Definition: address.hxx:270
void SetRow(SCROW nRowP)
Definition: address.hxx:274
const sal_uInt8 SC_DDE_IGNOREMODE
Definition: document.hxx:294
sal_uInt64 remainingSize()
void SetCol(SCCOL nColP)
Definition: address.hxx:278
TransliterationFlags
sal_uInt16 GetLen() const
void ImplCreateOptions()
Definition: documen8.cxx:100
constexpr double nPPTX
ocDde
void SetTab(SCTAB nTabP)
Definition: address.hxx:282
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
SvtScriptType
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
const SvBaseLinks & GetLinks() const
int i
SC_DLLPUBLIC bool FindDdeLink(std::u16string_view rAppl, std::u16string_view rTopic, std::u16string_view rItem, sal_uInt8 nMode, size_t &rnDdePos)
Tries to find a DDE link with the specified connection data.
Definition: documen8.cxx:959
void Remove(SvBaseLink const *pLink)
void IncCol(SCCOL nDelta=1)
Definition: address.hxx:303
void GetDimensions(SCSIZE &rC, SCSIZE &rR) const
Definition: scmatrix.cxx:2974
#define LANGUAGE_SYSTEM
const svl::SharedString * mpString
Definition: cellvalue.hxx:108
sal_Int16 SCCOL
Definition: types.hxx:21
SC_DLLPUBLIC const ScMatrix * GetDdeLinkResultMatrix(size_t nDdePos) const
Returns the result matrix of the specified DDE link.
Definition: documen8.cxx:987
bool GetDdeLinkData(size_t nDdePos, OUString &rAppl, OUString &rTopic, OUString &rItem) const
Returns the connection data of the specified DDE link.
Definition: documen8.cxx:965
#define SC_MOD()
Definition: scmod.hxx:249
bool HasAreaLinks() const
Definition: documen8.cxx:1034
SfxBindings & GetBindings()
bool GetDdeLinkMode(size_t nDdePos, sal_uInt8 &rnMode) const
Returns the link mode of the specified DDE link.
Definition: documen8.cxx:977
EEHorizontalTextDirection
bool RenamePageStyleInUse(std::u16string_view rOld, const OUString &rNew)
Definition: documen8.cxx:340
OUString ScResId(const char *pId)
Definition: scdll.cxx:89
#define LANGUAGE_DONTKNOW
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALUE_FORMAT(146)
static void DeleteInterpretProgress()
Definition: progress.cxx:154
ScColContainer aCol
Definition: table.hxx:156
void SaveDdeLinks(SvStream &rStream) const
Definition: documen8.cxx:709
static void CreateInterpretProgress(ScDocument *pDoc, bool bWait=true)
Definition: progress.cxx:134
const SCTAB MAXTAB
Definition: address.hxx:70
Use this class as a locale variable to merge number formatter from another document, and set NULL pointer to pFormatExchangeList when done.
Definition: document.hxx:2559
void UpdateRefAreaLinks(UpdateRefMode eUpdateRefMode, const ScRange &r, SCCOL nDx, SCROW nDy, SCTAB nDz)
Definition: documen8.cxx:1083
Reference not affected, no change at all.
Definition: refupdat.hxx:31
SCCOL Col() const
Definition: address.hxx:266
exports com.sun.star.chart2. data
SC_DLLPUBLIC ScMacroManager * GetMacroManager()
Definition: documen8.cxx:377
ocWebservice
Point LogicToPixel(const Point &rLogicPt) const
bool IdleCalcTextWidth()
Definition: documen8.cxx:532
void InvalidateTextWidth(std::u16string_view rStyleName)
Definition: documen8.cxx:295
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
constexpr TypedWhichId< SvxLanguageItem > ATTR_CTL_FONT_LANGUAGE(120)
CellType meType
Definition: cellvalue.hxx:105
void SetState(sal_uLong nVal, sal_uLong nNewRange=0)
Definition: progress.hxx:78
static bool GetDisplayNames(const SvBaseLink *, OUString *pType, OUString *pFile=nullptr, OUString *pLink=nullptr, OUString *pFilter=nullptr)
constexpr TypedWhichId< SvxFrameDirectionItem > ATTR_WRITINGDIR(138)
UpdateRefMode
Definition: global.hxx:309
void InsertDDELink(SvBaseLink *, const OUString &rServer, std::u16string_view rTopic, std::u16string_view rItem)
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
sal_Int32 SCROW
Definition: types.hxx:17
void UpdateExternalRefLinks(weld::Window *pWin)
Definition: documen8.cxx:789
EEHorizontalTextDirection GetEditTextDirection(SCTAB nTab) const
Definition: documen8.cxx:355
OUString aPageStyle
Definition: table.hxx:170
SC_DLLPUBLIC OutputDevice * GetRefDevice()
Definition: documen8.cxx:198
std::vector< tools::SvRef< SvBaseLink > > SvBaseLinks
static SfxViewFrame * Current()
SfxItemState
void SetPrintOptions()
Definition: documen8.cxx:160
#define SOFFICE_FILEFORMAT_40
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
SvBaseLink * pLink
unsigned char sal_uInt8
const SvNumberformat * GetEntry(sal_uInt32 nKey) const
bool IsCTLFontEnabled() const
SfxBindings * GetViewBindings()
Definition: documen8.cxx:1188
static VclPtr< reference_type > Create(Arg &&...arg)
static bool CheckWidthInvalidate(bool &bNumFormatChanged, const SfxItemSet &rNewAttrs, const SfxItemSet &rOldAttrs)
Definition: global.cxx:178
rtl_TextEncoding GetStreamCharSet() const
void * p
Reference< XComponentContext > getProcessComponentContext()
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:400
constexpr sal_uInt16 ATTR_PATTERN_END(155)
ScRefUpdateRes
Definition: refupdat.hxx:30
void DeleteAreaLinksOnTab(SCTAB nTab)
Definition: documen8.cxx:1064
SC_DLLPUBLIC ScStyleSheetPool * GetStyleSheetPool() const
Definition: document.cxx:6053
bool IsInLinkUpdate() const
Definition: documen8.cxx:784
bool bAutoCalc
Definition: document.hxx:482
bool ValidRow(SCROW nRow, SCROW nMaxRow)
Definition: address.hxx:98
reference_type * get() const
rtl::Reference< ScPoolHelper > mxPoolHelper
Definition: document.hxx:354
static SfxViewFrame * GetFirst(const SfxObjectShell *pDoc=nullptr, bool bOnlyVisible=true)
#define SAL_WARN(area, stream)
SC_DLLPUBLIC void CopyDdeLinks(ScDocument &rDestDoc) const
Definition: documen8.cxx:866
SCCOL ClampToAllocatedColumns(SCCOL nCol) const
Definition: table.hxx:1090
bool IsFormulaDirty(SCROW nRow) const
Definition: column.cxx:3220
void UpdateAreaLinks()
Definition: documen8.cxx:1049
constexpr TypedWhichId< SfxUInt16Item > ATTR_PAGE_SCALE(174)
bool ValidTab(SCTAB nTab)
Definition: address.hxx:104
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
static sal_uInt16 DoUpdateAllCharts(ScDocument &rDoc)
void ImplDeleteOptions()
Definition: documen8.cxx:106
LanguageType GetLanguage() const
sal_uInt16 nPos
sal_Int16 SCTAB
Definition: types.hxx:22
#define TEXTWIDTH_DIRTY
Definition: globalnames.hxx:17
void FillEditItemSet(SfxItemSet *pEditSet, const SfxItemSet *pCondSet=nullptr) const
Converts all Calc items contained in the own item set to edit engine items and puts them into pEditSe...
Definition: patattr.cxx:774
void KeyInput()
Definition: documen8.cxx:1180
bool HasOpCodeRPN(OpCode) const