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