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