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