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