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>
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 <com/sun/star/i18n/TransliterationModulesExtra.hpp>
50 #include "inputopt.hxx"
54 #include "poolhelp.hxx"
55 #include "docpool.hxx"
56 #include "stlpool.hxx"
57 #include "stlsheet.hxx"
58 #include "docoptio.hxx"
59 #include "viewopti.hxx"
60 #include "scextopt.hxx"
61 #include "rechead.hxx"
62 #include "ddelink.hxx"
63 #include "scmatrix.hxx"
64 #include "arealink.hxx"
65 #include "dociter.hxx"
66 #include "patattr.hxx"
68 #include "editutil.hxx"
69 #include "progress.hxx"
70 #include "document.hxx"
71 #include "chartlis.hxx"
72 #include "chartlock.hxx"
73 #include "refupdat.hxx"
74 #include "validat.hxx"
75 #include "markdata.hxx"
77 #include "printopt.hxx"
78 #include "externalrefmgr.hxx"
79 #include "globstr.hrc"
81 #include "charthelper.hxx"
82 #include "macromgr.hxx"
83 #include "dpobject.hxx"
85 #include "scresid.hxx"
86 #include "columniterator.hxx"
87 #include "globalnames.hxx"
88 #include "stringutil.hxx"
89 #include <documentlinkmgr.hxx>
90 #include <scopetools.hxx>
92 #include <boost/scoped_ptr.hpp>
94 using namespace com::sun::star
;
96 // STATIC DATA -----------------------------------------------------------
100 inline sal_uInt16
getScaleValue(SfxStyleSheetBase
& rStyle
, sal_uInt16 nWhich
)
102 return static_cast<const SfxUInt16Item
&>(rStyle
.GetItemSet().Get(nWhich
)).GetValue();
107 void ScDocument::ImplCreateOptions()
109 pDocOptions
= new ScDocOptions();
110 pViewOptions
= new ScViewOptions();
113 void ScDocument::ImplDeleteOptions()
117 delete pExtDocOptions
;
120 SfxPrinter
* ScDocument::GetPrinter(bool bCreateIfNotExist
)
122 if ( !pPrinter
&& bCreateIfNotExist
)
125 new SfxItemSet( *xPoolHelper
->GetDocPool(),
126 SID_PRINTER_NOTFOUND_WARN
, SID_PRINTER_NOTFOUND_WARN
,
127 SID_PRINTER_CHANGESTODOC
, SID_PRINTER_CHANGESTODOC
,
128 SID_PRINT_SELECTEDSHEET
, SID_PRINT_SELECTEDSHEET
,
129 SID_SCPRINTOPTIONS
, SID_SCPRINTOPTIONS
,
132 ::utl::MiscCfg aMisc
;
133 SfxPrinterChangeFlags nFlags
= SfxPrinterChangeFlags::NONE
;
134 if ( aMisc
.IsPaperOrientationWarning() )
135 nFlags
|= SfxPrinterChangeFlags::CHG_ORIENTATION
;
136 if ( aMisc
.IsPaperSizeWarning() )
137 nFlags
|= SfxPrinterChangeFlags::CHG_SIZE
;
138 pSet
->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC
, static_cast<int>(nFlags
) ) );
139 pSet
->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN
, aMisc
.IsNotFoundWarning() ) );
141 pPrinter
= VclPtr
<SfxPrinter
>::Create( pSet
);
142 pPrinter
->SetMapMode( MAP_100TH_MM
);
144 pPrinter
->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
150 void ScDocument::SetPrinter( SfxPrinter
* pNewPrinter
)
152 if ( pNewPrinter
== pPrinter
.get() )
154 // #i6706# SetPrinter is called with the same printer again if
155 // the JobSetup has changed. In that case just call UpdateDrawPrinter
156 // (SetRefDevice for drawing layer) because of changed text sizes.
161 ScopedVclPtr
<SfxPrinter
> pOld( pPrinter
);
162 pPrinter
= pNewPrinter
;
164 pPrinter
->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
166 InvalidateTextWidth(NULL
, NULL
, false); // in both cases
169 void ScDocument::SetPrintOptions()
171 if ( !pPrinter
) GetPrinter(); // this sets pPrinter
172 OSL_ENSURE( pPrinter
, "Error in printer creation :-/" );
176 ::utl::MiscCfg aMisc
;
177 SfxItemSet
aOptSet( pPrinter
->GetOptions() );
179 SfxPrinterChangeFlags nFlags
= SfxPrinterChangeFlags::NONE
;
180 if ( aMisc
.IsPaperOrientationWarning() )
181 nFlags
|= SfxPrinterChangeFlags::CHG_ORIENTATION
;
182 if ( aMisc
.IsPaperSizeWarning() )
183 nFlags
|= SfxPrinterChangeFlags::CHG_SIZE
;
184 aOptSet
.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC
, static_cast<int>(nFlags
) ) );
185 aOptSet
.Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN
, aMisc
.IsNotFoundWarning() ) );
187 pPrinter
->SetOptions( aOptSet
);
191 VirtualDevice
* ScDocument::GetVirtualDevice_100th_mm()
193 if (!pVirtualDevice_100th_mm
)
196 pVirtualDevice_100th_mm
= VclPtr
<VirtualDevice
>::Create( 8 );
198 pVirtualDevice_100th_mm
= VclPtr
<VirtualDevice
>::Create( 1 );
200 pVirtualDevice_100th_mm
->SetReferenceDevice(VirtualDevice::REFDEV_MODE_MSO1
);
201 MapMode
aMapMode( pVirtualDevice_100th_mm
->GetMapMode() );
202 aMapMode
.SetMapUnit( MAP_100TH_MM
);
203 pVirtualDevice_100th_mm
->SetMapMode( aMapMode
);
205 return pVirtualDevice_100th_mm
;
208 OutputDevice
* ScDocument::GetRefDevice()
210 // Create printer like ref device, see Writer...
211 OutputDevice
* pRefDevice
= NULL
;
212 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
213 pRefDevice
= GetPrinter();
215 pRefDevice
= GetVirtualDevice_100th_mm();
219 void ScDocument::ModifyStyleSheet( SfxStyleSheetBase
& rStyleSheet
,
220 const SfxItemSet
& rChanges
)
222 SfxItemSet
& rSet
= rStyleSheet
.GetItemSet();
224 switch ( rStyleSheet
.GetFamily() )
226 case SFX_STYLE_FAMILY_PAGE
:
228 const sal_uInt16 nOldScale
= getScaleValue(rStyleSheet
, ATTR_PAGE_SCALE
);
229 const sal_uInt16 nOldScaleToPages
= getScaleValue(rStyleSheet
, ATTR_PAGE_SCALETOPAGES
);
230 rSet
.Put( rChanges
);
231 const sal_uInt16 nNewScale
= getScaleValue(rStyleSheet
, ATTR_PAGE_SCALE
);
232 const sal_uInt16 nNewScaleToPages
= getScaleValue(rStyleSheet
, ATTR_PAGE_SCALETOPAGES
);
234 if ( (nOldScale
!= nNewScale
) || (nOldScaleToPages
!= nNewScaleToPages
) )
235 InvalidateTextWidth( rStyleSheet
.GetName() );
237 if( SvtLanguageOptions().IsCTLFontEnabled() )
239 const SfxPoolItem
*pItem
= NULL
;
240 if( rChanges
.GetItemState(ATTR_WRITINGDIR
, true, &pItem
) == SfxItemState::SET
)
241 ScChartHelper::DoUpdateAllCharts( this );
246 case SFX_STYLE_FAMILY_PARA
:
248 bool bNumFormatChanged
;
249 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged
,
251 InvalidateTextWidth( NULL
, NULL
, bNumFormatChanged
);
253 for (SCTAB nTab
=0; nTab
<=MAXTAB
; ++nTab
)
254 if (maTabs
[nTab
] && maTabs
[nTab
]->IsStreamValid())
255 maTabs
[nTab
]->SetStreamValid( false );
257 sal_uLong nOldFormat
=
258 static_cast<const SfxUInt32Item
*>(&rSet
.Get(
259 ATTR_VALUE_FORMAT
))->GetValue();
260 sal_uLong nNewFormat
=
261 static_cast<const SfxUInt32Item
*>(&rChanges
.Get(
262 ATTR_VALUE_FORMAT
))->GetValue();
263 LanguageType eNewLang
, eOldLang
;
264 eNewLang
= eOldLang
= LANGUAGE_DONTKNOW
;
265 if ( nNewFormat
!= nOldFormat
)
267 SvNumberFormatter
* pFormatter
= GetFormatTable();
268 eOldLang
= pFormatter
->GetEntry( nOldFormat
)->GetLanguage();
269 eNewLang
= pFormatter
->GetEntry( nNewFormat
)->GetLanguage();
272 // Explanation to Items in rChanges:
273 // Set Item - take over change
274 // Dontcare - Set Default
275 // Default - No change
276 // ("no change" is not possible with PutExtended, thus the loop)
277 for (sal_uInt16 nWhich
= ATTR_PATTERN_START
; nWhich
<= ATTR_PATTERN_END
; nWhich
++)
279 const SfxPoolItem
* pItem
;
280 SfxItemState eState
= rChanges
.GetItemState( nWhich
, false, &pItem
);
281 if ( eState
== SfxItemState::SET
)
283 else if ( eState
== SfxItemState::DONTCARE
)
284 rSet
.ClearItem( nWhich
);
285 // when Default nothing
288 if ( eNewLang
!= eOldLang
)
290 SvxLanguageItem( eNewLang
, ATTR_LANGUAGE_FORMAT
) );
295 // added to avoid warnings
300 void ScDocument::CopyStdStylesFrom( ScDocument
* pSrcDoc
)
302 // number format exchange list has to be handled here, too
303 NumFmtMergeHandler
aNumFmtMergeHdl(this, pSrcDoc
);
304 xPoolHelper
->GetStylePool()->CopyStdStylesFrom( pSrcDoc
->xPoolHelper
->GetStylePool() );
307 void ScDocument::InvalidateTextWidth( const OUString
& rStyleName
)
309 const SCTAB nCount
= GetTableCount();
310 for ( SCTAB i
=0; i
<nCount
&& maTabs
[i
]; i
++ )
311 if ( maTabs
[i
]->GetPageStyle() == rStyleName
)
312 InvalidateTextWidth( i
);
315 void ScDocument::InvalidateTextWidth( SCTAB nTab
)
317 ScAddress
aAdrFrom( 0, 0, nTab
);
318 ScAddress
aAdrTo ( MAXCOL
, MAXROW
, nTab
);
319 InvalidateTextWidth( &aAdrFrom
, &aAdrTo
, false );
322 bool ScDocument::IsPageStyleInUse( const OUString
& rStrPageStyle
, SCTAB
* pInTab
)
325 const SCTAB nCount
= GetTableCount();
328 for ( i
= 0; !bInUse
&& i
< nCount
&& maTabs
[i
]; i
++ )
329 bInUse
= ( maTabs
[i
]->GetPageStyle() == rStrPageStyle
);
337 bool ScDocument::RemovePageStyleInUse( const OUString
& rStyle
)
339 bool bWasInUse
= false;
340 const SCTAB nCount
= GetTableCount();
342 for ( SCTAB i
=0; i
<nCount
&& maTabs
[i
]; i
++ )
343 if ( maTabs
[i
]->GetPageStyle() == rStyle
)
346 maTabs
[i
]->SetPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD
) );
352 bool ScDocument::RenamePageStyleInUse( const OUString
& rOld
, const OUString
& rNew
)
354 bool bWasInUse
= false;
355 const SCTAB nCount
= GetTableCount();
357 for ( SCTAB i
=0; i
<nCount
&& maTabs
[i
]; i
++ )
358 if ( maTabs
[i
]->GetPageStyle() == rOld
)
361 maTabs
[i
]->SetPageStyle( rNew
);
367 sal_uInt8
ScDocument::GetEditTextDirection(SCTAB nTab
) const
369 EEHorizontalTextDirection eRet
= EE_HTEXTDIR_DEFAULT
;
371 OUString aStyleName
= GetPageStyle( nTab
);
372 SfxStyleSheetBase
* pStyle
= xPoolHelper
->GetStylePool()->Find( aStyleName
, SFX_STYLE_FAMILY_PAGE
);
375 SfxItemSet
& rStyleSet
= pStyle
->GetItemSet();
376 SvxFrameDirection eDirection
= (SvxFrameDirection
)
377 static_cast<const SvxFrameDirectionItem
&>(rStyleSet
.Get( ATTR_WRITINGDIR
)).GetValue();
379 if ( eDirection
== FRMDIR_HORI_LEFT_TOP
)
380 eRet
= EE_HTEXTDIR_L2R
;
381 else if ( eDirection
== FRMDIR_HORI_RIGHT_TOP
)
382 eRet
= EE_HTEXTDIR_R2L
;
383 // else (invalid for EditEngine): keep "default"
386 return sal::static_int_cast
<sal_uInt8
>(eRet
);
389 ScMacroManager
* ScDocument::GetMacroManager()
391 if (!mpMacroMgr
.get())
392 mpMacroMgr
.reset(new ScMacroManager(this));
393 return mpMacroMgr
.get();
396 void ScDocument::FillMatrix(
397 ScMatrix
& rMat
, SCTAB nTab
, SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
) const
399 const ScTable
* pTab
= FetchTable(nTab
);
403 if (nCol1
> nCol2
|| nRow1
> nRow2
)
407 rMat
.GetDimensions(nC
, nR
);
408 if (static_cast<SCROW
>(nR
) != nRow2
- nRow1
+ 1 || static_cast<SCCOL
>(nC
) != nCol2
- nCol1
+ 1)
411 pTab
->FillMatrix(rMat
, nCol1
, nRow1
, nCol2
, nRow2
);
414 void ScDocument::SetFormulaResults( const ScAddress
& rTopPos
, const double* pResults
, size_t nLen
)
416 ScTable
* pTab
= FetchTable(rTopPos
.Tab());
420 pTab
->SetFormulaResults(rTopPos
.Col(), rTopPos
.Row(), pResults
, nLen
);
423 void ScDocument::SetFormulaResults(
424 const ScAddress
& rTopPos
, const formula::FormulaTokenRef
* pResults
, size_t nLen
)
426 ScTable
* pTab
= FetchTable(rTopPos
.Tab());
430 pTab
->SetFormulaResults(rTopPos
.Col(), rTopPos
.Row(), pResults
, nLen
);
433 void ScDocument::InvalidateTextWidth( const ScAddress
* pAdrFrom
, const ScAddress
* pAdrTo
,
434 bool bNumFormatChanged
)
436 bool bBroadcast
= (bNumFormatChanged
&& GetDocOptions().IsCalcAsShown() && !IsImportingXML() && !IsClipboard());
437 if ( pAdrFrom
&& !pAdrTo
)
439 const SCTAB nTab
= pAdrFrom
->Tab();
441 if (nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
442 maTabs
[nTab
]->InvalidateTextWidth( pAdrFrom
, NULL
, bNumFormatChanged
, bBroadcast
);
446 const SCTAB nTabStart
= pAdrFrom
? pAdrFrom
->Tab() : 0;
447 const SCTAB nTabEnd
= pAdrTo
? pAdrTo
->Tab() : MAXTAB
;
449 for ( SCTAB nTab
=nTabStart
; nTab
<=nTabEnd
&& nTab
< static_cast<SCTAB
>(maTabs
.size()); nTab
++ )
451 maTabs
[nTab
]->InvalidateTextWidth( pAdrFrom
, pAdrTo
, bNumFormatChanged
, bBroadcast
);
455 #define CALCMAX 1000 // Calculations
459 class IdleCalcTextWidthScope
462 ScAddress
& mrCalcPos
;
463 MapMode maOldMapMode
;
464 sal_uInt64 mnStartTime
;
465 ScStyleSheetPool
* mpStylePool
;
466 sal_uInt16 mnOldSearchMask
;
467 SfxStyleFamily meOldFamily
;
472 IdleCalcTextWidthScope(ScDocument
& rDoc
, ScAddress
& rCalcPos
) :
475 mnStartTime(tools::Time::GetSystemTicks()),
476 mpStylePool(rDoc
.GetStyleSheetPool()),
477 mnOldSearchMask(mpStylePool
->GetSearchMask()),
478 meOldFamily(mpStylePool
->GetSearchFamily()),
482 // The old search mask / family flags must be restored so that e.g.
483 // the styles dialog shows correct listing when it's opened in-between
486 mrDoc
.EnableIdle(false);
487 mpStylePool
->SetSearchMask(SFX_STYLE_FAMILY_PAGE
, SFXSTYLEBIT_ALL
);
490 ~IdleCalcTextWidthScope()
492 SfxPrinter
* pDev
= mrDoc
.GetPrinter();
494 pDev
->SetMapMode(maOldMapMode
);
497 ScProgress::DeleteInterpretProgress();
499 mpStylePool
->SetSearchMask(meOldFamily
, mnOldSearchMask
);
500 mrDoc
.EnableIdle(true);
503 SCTAB
Tab() const { return mrCalcPos
.Tab(); }
504 SCCOL
Col() const { return mrCalcPos
.Col(); }
505 SCROW
Row() const { return mrCalcPos
.Row(); }
507 void setTab(SCTAB nTab
) { mrCalcPos
.SetTab(nTab
); }
508 void setCol(SCCOL nCol
) { mrCalcPos
.SetCol(nCol
); }
509 void setRow(SCROW nRow
) { mrCalcPos
.SetRow(nRow
); }
511 void incTab(SCTAB nInc
=1) { mrCalcPos
.IncTab(nInc
); }
512 void incCol(SCCOL nInc
=1) { mrCalcPos
.IncCol(nInc
); }
514 void setOldMapMode(const MapMode
& rOldMapMode
) { maOldMapMode
= rOldMapMode
; }
516 void setNeedMore(bool b
) { mbNeedMore
= b
; }
517 bool getNeedMore() const { return mbNeedMore
; }
519 sal_uInt64
getStartTime() const { return mnStartTime
; }
521 void createProgressBar()
523 ScProgress::CreateInterpretProgress(&mrDoc
, false);
527 bool hasProgressBar() const { return mbProgress
; }
529 ScStyleSheetPool
* getStylePool() { return mpStylePool
; }
534 bool ScDocument::IdleCalcTextWidth() // true = try next again
536 // #i75610# if a printer hasn't been set or created yet, don't create one for this
537 if (!mbIdleEnabled
|| IsInLinkUpdate() || GetPrinter(false) == NULL
)
540 IdleCalcTextWidthScope
aScope(*this, aCurTextWidthCalcPos
);
542 if (!ValidRow(aScope
.Row()))
548 if (aScope
.Col() < 0)
550 aScope
.setCol(MAXCOL
);
554 if (!ValidTab(aScope
.Tab()) || aScope
.Tab() >= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[aScope
.Tab()])
557 ScTable
* pTab
= maTabs
[aScope
.Tab()];
558 ScStyleSheet
* pStyle
= static_cast<ScStyleSheet
*>(aScope
.getStylePool()->Find(pTab
->aPageStyle
, SFX_STYLE_FAMILY_PAGE
));
559 OSL_ENSURE( pStyle
, "Missing StyleSheet :-/" );
561 if (!pStyle
|| getScaleValue(*pStyle
, ATTR_PAGE_SCALETOPAGES
) == 0)
563 // Move to the next sheet as the current one has scale-to-pages set,
569 sal_uInt16 nZoom
= getScaleValue(*pStyle
, ATTR_PAGE_SCALE
);
570 Fraction
aZoomFract(nZoom
, 100);
572 // Start at specified cell position (nCol, nRow, nTab).
573 ScColumn
* pCol
= &pTab
->aCol
[aScope
.Col()];
574 boost::scoped_ptr
<ScColumnTextWidthIterator
> pColIter(new ScColumnTextWidthIterator(*pCol
, aScope
.Row(), MAXROW
));
576 OutputDevice
* pDev
= NULL
;
577 sal_uInt16 nRestart
= 0;
578 sal_uInt16 nCount
= 0;
579 while ( (nZoom
> 0) && (nCount
< CALCMAX
) && (nRestart
< 2) )
581 if (pColIter
->hasCell())
583 // More cell in this column.
584 SCROW nRow
= pColIter
->getPos();
587 if (pColIter
->getValue() == TEXTWIDTH_DIRTY
)
589 // Calculate text width for this cell.
595 aScope
.setOldMapMode(pDev
->GetMapMode());
596 pDev
->SetMapMode( MAP_PIXEL
); // Important for GetNeededSize
598 Point aPix1000
= pDev
->LogicToPixel( Point(1000,1000), MAP_TWIP
);
599 nPPTX
= aPix1000
.X() / 1000.0;
600 nPPTY
= aPix1000
.Y() / 1000.0;
603 if (!aScope
.hasProgressBar() && pCol
->IsFormulaDirty(nRow
))
604 aScope
.createProgressBar();
606 sal_uInt16 nNewWidth
= (sal_uInt16
)GetNeededSize(
607 aScope
.Col(), aScope
.Row(), aScope
.Tab(),
608 pDev
, nPPTX
, nPPTY
, aZoomFract
,aZoomFract
, true, true); // bTotalSize
610 pColIter
->setValue(nNewWidth
);
611 aScope
.setNeedMore(true);
617 // No more cell in this column. Move to the left column and start at row 0.
619 bool bNewTab
= false;
624 if (aScope
.Col() < 0)
626 // No more column to the left. Move to the right-most column of the next sheet.
627 aScope
.setCol(MAXCOL
);
632 if (!ValidTab(aScope
.Tab()) || aScope
.Tab() >= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[aScope
.Tab()] )
634 // Sheet doesn't exist at specified sheet position. Restart at sheet 0.
644 pTab
= maTabs
[aScope
.Tab()];
645 pStyle
= static_cast<ScStyleSheet
*>(aScope
.getStylePool()->Find(
646 pTab
->aPageStyle
, SFX_STYLE_FAMILY_PAGE
));
650 // Check if the scale-to-pages setting is set. If
651 // set, we exit the loop. If not, get the page
652 // scale factor of the new sheet.
653 if (getScaleValue(*pStyle
, ATTR_PAGE_SCALETOPAGES
) == 0)
655 nZoom
= getScaleValue(*pStyle
, ATTR_PAGE_SCALE
);
656 aZoomFract
= Fraction(nZoom
, 100);
663 OSL_FAIL( "Missing StyleSheet :-/" );
669 pCol
= &pTab
->aCol
[aScope
.Col()];
670 pColIter
.reset(new ScColumnTextWidthIterator(*pCol
, aScope
.Row(), MAXROW
));
674 aScope
.incTab(); // Move to the next sheet as the current one has scale-to-pages set.
682 // Quit if either 1) its duration exceeds 50 ms, or 2) there is any
683 // pending event after processing 32 cells.
684 VclInputFlags ABORT_EVENTS
= VCL_INPUT_ANY
;
685 ABORT_EVENTS
&= ~VclInputFlags::TIMER
;
686 ABORT_EVENTS
&= ~VclInputFlags::OTHER
;
687 if ((50L < tools::Time::GetSystemTicks() - aScope
.getStartTime()) || (nCount
> 31 && Application::AnyInput(ABORT_EVENTS
)))
691 return aScope
.getNeedMore();
694 void ScDocument::RepaintRange( const ScRange
& rRange
)
696 if ( bIsVisible
&& pShell
)
698 ScModelObj
* pModel
= ScModelObj::getImplementation( pShell
->GetModel() );
700 pModel
->RepaintRange( rRange
); // locked repaints are checked there
704 void ScDocument::RepaintRange( const ScRangeList
& rRange
)
706 if ( bIsVisible
&& pShell
)
708 ScModelObj
* pModel
= ScModelObj::getImplementation( pShell
->GetModel() );
710 pModel
->RepaintRange( rRange
); // locked repaints are checked there
714 void ScDocument::SaveDdeLinks(SvStream
& rStream
) const
716 // when 4.0-Export, remove all with mode != DEFAULT
717 bool bExport40
= ( rStream
.GetVersion() <= SOFFICE_FILEFORMAT_40
);
719 const ::sfx2::SvBaseLinks
& rLinks
= GetLinkManager()->GetLinks();
720 sal_uInt16 nCount
= rLinks
.size();
724 sal_uInt16 nDdeCount
= 0;
726 for (i
=0; i
<nCount
; i
++)
728 ::sfx2::SvBaseLink
* pBase
= *rLinks
[i
];
729 if (pBase
->ISA(ScDdeLink
))
730 if ( !bExport40
|| static_cast<ScDdeLink
*>(pBase
)->GetMode() == SC_DDE_DEFAULT
)
736 ScMultipleWriteHeader
aHdr( rStream
);
737 rStream
.WriteUInt16( nDdeCount
);
741 for (i
=0; i
<nCount
; i
++)
743 ::sfx2::SvBaseLink
* pBase
= *rLinks
[i
];
744 if (pBase
->ISA(ScDdeLink
))
746 ScDdeLink
* pLink
= static_cast<ScDdeLink
*>(pBase
);
747 if ( !bExport40
|| pLink
->GetMode() == SC_DDE_DEFAULT
)
748 pLink
->Store( rStream
, aHdr
);
753 void ScDocument::LoadDdeLinks(SvStream
& rStream
)
755 sfx2::LinkManager
* pMgr
= GetDocLinkManager().getLinkManager(bAutoCalc
);
759 ScMultipleReadHeader
aHdr( rStream
);
761 sal_uInt16
nCount(0);
762 rStream
.ReadUInt16( nCount
);
764 const rtl_TextEncoding eCharSet
= rStream
.GetStreamCharSet();
765 const size_t nMinStringSize
= eCharSet
== RTL_TEXTENCODING_UNICODE
? sizeof(sal_uInt32
) : sizeof(sal_uInt16
);
766 const size_t nMinRecordSize
= 1 + nMinStringSize
*3;
767 const size_t nMaxRecords
= rStream
.remainingSize() / nMinRecordSize
;
768 if (nCount
> nMaxRecords
)
770 SAL_WARN("sc", "Parsing error: " << nMaxRecords
<<
771 " max possible entries, but " << nCount
<< " claimed, truncating");
772 nCount
= nMaxRecords
;
775 for (sal_uInt16 i
=0; i
<nCount
; ++i
)
777 ScDdeLink
* pLink
= new ScDdeLink( this, rStream
, aHdr
);
778 pMgr
->InsertDDELink(pLink
, pLink
->GetAppl(), pLink
->GetTopic(), pLink
->GetItem());
782 void ScDocument::SetInLinkUpdate(bool bSet
)
784 // called from TableLink and AreaLink
786 OSL_ENSURE( bInLinkUpdate
!= bSet
, "SetInLinkUpdate twice" );
787 bInLinkUpdate
= bSet
;
790 bool ScDocument::IsInLinkUpdate() const
792 return bInLinkUpdate
|| IsInDdeLinkUpdate();
795 void ScDocument::UpdateExternalRefLinks(vcl::Window
* pWin
)
797 if (!pExternalRefMgr
.get())
800 sfx2::LinkManager
* pMgr
= GetDocLinkManager().getLinkManager(bAutoCalc
);
804 const ::sfx2::SvBaseLinks
& rLinks
= pMgr
->GetLinks();
805 sal_uInt16 nCount
= rLinks
.size();
809 // Collect all the external ref links first.
810 std::vector
<ScExternalRefLink
*> aRefLinks
;
811 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
813 ::sfx2::SvBaseLink
* pBase
= *rLinks
[i
];
814 ScExternalRefLink
* pRefLink
= dynamic_cast<ScExternalRefLink
*>(pBase
);
816 aRefLinks
.push_back(pRefLink
);
819 sc::WaitPointerSwitch
aWaitSwitch(pWin
);
821 pExternalRefMgr
->enableDocTimer(false);
822 ScProgress
aProgress(GetDocumentShell(), ScResId(SCSTR_UPDATE_EXTDOCS
).toString(), aRefLinks
.size());
823 for (size_t i
= 0, n
= aRefLinks
.size(); i
< n
; ++i
)
825 aProgress
.SetState(i
+1);
827 ScExternalRefLink
* pRefLink
= aRefLinks
[i
];
828 if (pRefLink
->Update())
834 // Update failed. Notify the user.
837 sfx2::LinkManager::GetDisplayNames(pRefLink
, NULL
, &aFile
, NULL
, NULL
);
838 // Decode encoded URL for display friendliness.
839 INetURLObject
aUrl(aFile
,INetURLObject::WAS_ENCODED
);
840 aFile
= aUrl
.GetMainURL(INetURLObject::DECODE_UNAMBIGUOUS
);
843 aBuf
.append(OUString(ScResId(SCSTR_EXTDOC_NOT_LOADED
)));
844 aBuf
.appendAscii("\n\n");
846 ScopedVclPtrInstance
< MessageDialog
> aBox(pWin
, aBuf
.makeStringAndClear());
850 pExternalRefMgr
->enableDocTimer(true);
855 pShell
->Broadcast( SfxSimpleHint(FID_DATACHANGED
) );
857 // #i101960# set document modified, as in TrackTimeHdl for DDE links
858 if (!pShell
->IsModified())
860 pShell
->SetModified( true );
861 SfxBindings
* pBindings
= GetViewBindings();
864 pBindings
->Invalidate( SID_SAVEDOC
);
865 pBindings
->Invalidate( SID_DOC_MODIFIED
);
871 void ScDocument::CopyDdeLinks( ScDocument
* pDestDoc
) const
873 if (bIsClip
) // Create from Stream
878 pDestDoc
->LoadDdeLinks(*pClipData
);
884 const sfx2::LinkManager
* pMgr
= GetDocLinkManager().getExistingLinkManager();
888 sfx2::LinkManager
* pDestMgr
= pDestDoc
->GetDocLinkManager().getLinkManager(pDestDoc
->bAutoCalc
);
892 const sfx2::SvBaseLinks
& rLinks
= pMgr
->GetLinks();
893 for (size_t i
= 0, n
= rLinks
.size(); i
< n
; ++i
)
895 const sfx2::SvBaseLink
* pBase
= *rLinks
[i
];
896 if (pBase
->ISA(ScDdeLink
))
898 const ScDdeLink
* p
= static_cast<const ScDdeLink
*>(pBase
);
899 ScDdeLink
* pNew
= new ScDdeLink(pDestDoc
, *p
);
900 pDestMgr
->InsertDDELink(
901 pNew
, pNew
->GetAppl(), pNew
->GetTopic(), pNew
->GetItem());
908 /** Tries to find the specified DDE link.
909 @param pnDdePos (out-param) if not 0, the index of the DDE link is returned here
910 (does not include other links from link manager).
911 @return The DDE link, if it exists, otherwise 0. */
912 ScDdeLink
* lclGetDdeLink(
913 const sfx2::LinkManager
* pLinkManager
,
914 const OUString
& rAppl
, const OUString
& rTopic
, const OUString
& rItem
, sal_uInt8 nMode
,
915 size_t* pnDdePos
= NULL
)
919 const ::sfx2::SvBaseLinks
& rLinks
= pLinkManager
->GetLinks();
920 size_t nCount
= rLinks
.size();
921 if( pnDdePos
) *pnDdePos
= 0;
922 for( size_t nIndex
= 0; nIndex
< nCount
; ++nIndex
)
924 ::sfx2::SvBaseLink
* pLink
= *rLinks
[ nIndex
];
925 if( ScDdeLink
* pDdeLink
= PTR_CAST( ScDdeLink
, pLink
) )
927 if( (OUString(pDdeLink
->GetAppl()) == rAppl
) &&
928 (OUString(pDdeLink
->GetTopic()) == rTopic
) &&
929 (OUString(pDdeLink
->GetItem()) == rItem
) &&
930 ((nMode
== SC_DDE_IGNOREMODE
) || (nMode
== pDdeLink
->GetMode())) )
932 if( pnDdePos
) ++*pnDdePos
;
939 /** Returns a pointer to the specified DDE link.
940 @param nDdePos Index of the DDE link (does not include other links from link manager).
941 @return The DDE link, if it exists, otherwise 0. */
942 ScDdeLink
* lclGetDdeLink( const sfx2::LinkManager
* pLinkManager
, size_t nDdePos
)
946 const ::sfx2::SvBaseLinks
& rLinks
= pLinkManager
->GetLinks();
947 size_t nCount
= rLinks
.size();
948 size_t nDdeIndex
= 0; // counts only the DDE links
949 for( size_t nIndex
= 0; nIndex
< nCount
; ++nIndex
)
951 ::sfx2::SvBaseLink
* pLink
= *rLinks
[ nIndex
];
952 if( ScDdeLink
* pDdeLink
= PTR_CAST( ScDdeLink
, pLink
) )
954 if( nDdeIndex
== nDdePos
)
965 bool ScDocument::FindDdeLink( const OUString
& rAppl
, const OUString
& rTopic
, const OUString
& rItem
,
966 sal_uInt8 nMode
, size_t& rnDdePos
)
968 return lclGetDdeLink( GetLinkManager(), rAppl
, rTopic
, rItem
, nMode
, &rnDdePos
) != NULL
;
971 bool ScDocument::GetDdeLinkData( size_t nDdePos
, OUString
& rAppl
, OUString
& rTopic
, OUString
& rItem
) const
973 if( const ScDdeLink
* pDdeLink
= lclGetDdeLink( GetLinkManager(), nDdePos
) )
975 rAppl
= pDdeLink
->GetAppl();
976 rTopic
= pDdeLink
->GetTopic();
977 rItem
= pDdeLink
->GetItem();
983 bool ScDocument::GetDdeLinkMode( size_t nDdePos
, sal_uInt8
& rnMode
) const
985 if( const ScDdeLink
* pDdeLink
= lclGetDdeLink( GetLinkManager(), nDdePos
) )
987 rnMode
= pDdeLink
->GetMode();
993 const ScMatrix
* ScDocument::GetDdeLinkResultMatrix( size_t nDdePos
) const
995 const ScDdeLink
* pDdeLink
= lclGetDdeLink( GetLinkManager(), nDdePos
);
996 return pDdeLink
? pDdeLink
->GetResult() : NULL
;
999 bool ScDocument::CreateDdeLink( const OUString
& rAppl
, const OUString
& rTopic
, const OUString
& rItem
, sal_uInt8 nMode
, ScMatrixRef pResults
)
1001 /* Create a DDE link without updating it (i.e. for Excel import), to prevent
1002 unwanted connections. First try to find existing link. Set result array
1003 on existing and new links. */
1004 //TODO: store DDE links additionally at document (for efficiency)?
1005 OSL_ENSURE( nMode
!= SC_DDE_IGNOREMODE
, "ScDocument::CreateDdeLink - SC_DDE_IGNOREMODE not allowed here" );
1007 sfx2::LinkManager
* pMgr
= GetDocLinkManager().getLinkManager(bAutoCalc
);
1011 if (nMode
!= SC_DDE_IGNOREMODE
)
1013 ScDdeLink
* pDdeLink
= lclGetDdeLink(pMgr
, rAppl
, rTopic
, rItem
, nMode
);
1016 // create a new DDE link, but without TryUpdate
1017 pDdeLink
= new ScDdeLink( this, rAppl
, rTopic
, rItem
, nMode
);
1018 pMgr
->InsertDDELink(pDdeLink
, rAppl
, rTopic
, rItem
);
1021 // insert link results
1023 pDdeLink
->SetResult( pResults
);
1030 bool ScDocument::SetDdeLinkResultMatrix( size_t nDdePos
, ScMatrixRef pResults
)
1032 if( ScDdeLink
* pDdeLink
= lclGetDdeLink( GetLinkManager(), nDdePos
) )
1034 pDdeLink
->SetResult( pResults
);
1040 bool ScDocument::HasAreaLinks() const
1042 const sfx2::LinkManager
* pMgr
= GetDocLinkManager().getExistingLinkManager();
1046 const ::sfx2::SvBaseLinks
& rLinks
= pMgr
->GetLinks();
1047 sal_uInt16 nCount
= rLinks
.size();
1048 for (sal_uInt16 i
=0; i
<nCount
; i
++)
1049 if ((*rLinks
[i
])->ISA(ScAreaLink
))
1055 void ScDocument::UpdateAreaLinks()
1057 sfx2::LinkManager
* pMgr
= GetDocLinkManager().getLinkManager(false);
1061 const ::sfx2::SvBaseLinks
& rLinks
= pMgr
->GetLinks();
1062 for (sal_uInt16 i
=0; i
<rLinks
.size(); i
++)
1064 ::sfx2::SvBaseLink
* pBase
= *rLinks
[i
];
1065 if (pBase
->ISA(ScAreaLink
))
1070 void ScDocument::DeleteAreaLinksOnTab( SCTAB nTab
)
1072 sfx2::LinkManager
* pMgr
= GetDocLinkManager().getLinkManager(false);
1076 const ::sfx2::SvBaseLinks
& rLinks
= pMgr
->GetLinks();
1077 sal_uInt16 nPos
= 0;
1078 while ( nPos
< rLinks
.size() )
1080 const ::sfx2::SvBaseLink
* pBase
= *rLinks
[nPos
];
1081 if ( pBase
->ISA(ScAreaLink
) &&
1082 static_cast<const ScAreaLink
*>(pBase
)->GetDestArea().aStart
.Tab() == nTab
)
1089 void ScDocument::UpdateRefAreaLinks( UpdateRefMode eUpdateRefMode
,
1090 const ScRange
& rRange
, SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
)
1092 sfx2::LinkManager
* pMgr
= GetDocLinkManager().getLinkManager(false);
1096 bool bAnyUpdate
= false;
1098 const ::sfx2::SvBaseLinks
& rLinks
= pMgr
->GetLinks();
1099 sal_uInt16 nCount
= rLinks
.size();
1100 for (sal_uInt16 i
=0; i
<nCount
; i
++)
1102 ::sfx2::SvBaseLink
* pBase
= *rLinks
[i
];
1103 if (pBase
->ISA(ScAreaLink
))
1105 ScAreaLink
* pLink
= static_cast<ScAreaLink
*>(pBase
);
1106 ScRange aOutRange
= pLink
->GetDestArea();
1108 SCCOL nCol1
= aOutRange
.aStart
.Col();
1109 SCROW nRow1
= aOutRange
.aStart
.Row();
1110 SCTAB nTab1
= aOutRange
.aStart
.Tab();
1111 SCCOL nCol2
= aOutRange
.aEnd
.Col();
1112 SCROW nRow2
= aOutRange
.aEnd
.Row();
1113 SCTAB nTab2
= aOutRange
.aEnd
.Tab();
1115 ScRefUpdateRes eRes
=
1116 ScRefUpdate::Update( this, eUpdateRefMode
,
1117 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
1118 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(), nDx
, nDy
, nDz
,
1119 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
1120 if ( eRes
!= UR_NOTHING
)
1122 pLink
->SetDestArea( ScRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
) );
1130 // #i52120# Look for duplicates (after updating all positions).
1131 // If several links start at the same cell, the one with the lower index is removed
1132 // (file format specifies only one link definition for a cell).
1134 sal_uInt16 nFirstIndex
= 0;
1135 while ( nFirstIndex
< nCount
)
1137 bool bFound
= false;
1138 ::sfx2::SvBaseLink
* pFirst
= *rLinks
[nFirstIndex
];
1139 if ( pFirst
->ISA(ScAreaLink
) )
1141 ScAddress aFirstPos
= static_cast<ScAreaLink
*>(pFirst
)->GetDestArea().aStart
;
1142 for ( sal_uInt16 nSecondIndex
= nFirstIndex
+ 1; nSecondIndex
< nCount
&& !bFound
; ++nSecondIndex
)
1144 ::sfx2::SvBaseLink
* pSecond
= *rLinks
[nSecondIndex
];
1145 if ( pSecond
->ISA(ScAreaLink
) &&
1146 static_cast<ScAreaLink
*>(pSecond
)->GetDestArea().aStart
== aFirstPos
)
1148 // remove the first link, exit the inner loop, don't increment nFirstIndex
1149 pMgr
->Remove(pFirst
);
1150 nCount
= rLinks
.size();
1162 void ScDocument::KeyInput( const KeyEvent
& )
1164 if ( pChartListenerCollection
->hasListeners() )
1165 pChartListenerCollection
->StartTimer();
1166 if( apTemporaryChartLock
.get() )
1167 apTemporaryChartLock
->StartOrContinueLocking();
1170 bool ScDocument::CheckMacroWarn()
1172 // The check for macro configuration, macro warning and disabling is now handled
1173 // in SfxObjectShell::AdjustMacroMode, called by SfxObjectShell::CallBasic.
1178 SfxBindings
* ScDocument::GetViewBindings()
1180 // used to invalidate slots after changes to this document
1183 return NULL
; // no ObjShell -> no view
1185 // first check current view
1186 SfxViewFrame
* pViewFrame
= SfxViewFrame::Current();
1187 if ( pViewFrame
&& pViewFrame
->GetObjectShell() != pShell
) // wrong document?
1190 // otherwise use first view for this doc
1192 pViewFrame
= SfxViewFrame::GetFirst( pShell
);
1195 return &pViewFrame
->GetBindings();
1200 void ScDocument::TransliterateText( const ScMarkData
& rMultiMark
, sal_Int32 nType
)
1202 OSL_ENSURE( rMultiMark
.IsMultiMarked(), "TransliterateText: no selection" );
1204 utl::TransliterationWrapper
aTransliterationWrapper( comphelper::getProcessComponentContext(), nType
);
1205 bool bConsiderLanguage
= aTransliterationWrapper
.needLanguageForTheMode();
1206 sal_uInt16 nLanguage
= LANGUAGE_SYSTEM
;
1208 boost::scoped_ptr
<ScEditEngineDefaulter
> pEngine
; // not using pEditEngine member because of defaults
1210 SCTAB nCount
= GetTableCount();
1211 ScMarkData::const_iterator itr
= rMultiMark
.begin(), itrEnd
= rMultiMark
.end();
1212 for (; itr
!= itrEnd
&& *itr
< nCount
; ++itr
)
1219 bool bFound
= rMultiMark
.IsCellMarked( nCol
, nRow
);
1221 bFound
= GetNextMarkedCell( nCol
, nRow
, nTab
, rMultiMark
);
1225 ScRefCellValue aCell
;
1226 aCell
.assign(*this, ScAddress(nCol
, nRow
, nTab
));
1228 // fdo#32786 TITLE_CASE/SENTENCE_CASE need the extra handling in EditEngine (loop over words/sentences).
1229 // Still use TransliterationWrapper directly for text cells with other transliteration types,
1230 // for performance reasons.
1231 if (aCell
.meType
== CELLTYPE_EDIT
||
1232 (aCell
.meType
== CELLTYPE_STRING
&&
1233 ( nType
== i18n::TransliterationModulesExtra::SENTENCE_CASE
|| nType
== i18n::TransliterationModulesExtra::TITLE_CASE
)))
1236 pEngine
.reset(new ScFieldEditEngine(this, GetEnginePool(), GetEditPool()));
1238 // defaults from cell attributes must be set so right language is used
1239 const ScPatternAttr
* pPattern
= GetPattern( nCol
, nRow
, nTab
);
1240 SfxItemSet
* pDefaults
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
1241 if ( ScStyleSheet
* pPreviewStyle
= GetPreviewCellStyle( nCol
, nRow
, nTab
) )
1243 boost::scoped_ptr
<ScPatternAttr
> pPreviewPattern(new ScPatternAttr( *pPattern
));
1244 pPreviewPattern
->SetStyleSheet(pPreviewStyle
);
1245 pPreviewPattern
->FillEditItemSet( pDefaults
);
1249 SfxItemSet
* pFontSet
= GetPreviewFont( nCol
, nRow
, nTab
);
1250 pPattern
->FillEditItemSet( pDefaults
, pFontSet
);
1252 pEngine
->SetDefaults( pDefaults
, true );
1253 if (aCell
.meType
== CELLTYPE_STRING
)
1254 pEngine
->SetText(aCell
.mpString
->getString());
1255 else if (aCell
.mpEditText
)
1256 pEngine
->SetText(*aCell
.mpEditText
);
1258 pEngine
->ClearModifyFlag();
1260 sal_Int32 nLastPar
= pEngine
->GetParagraphCount();
1263 sal_Int32 nTxtLen
= pEngine
->GetTextLen(nLastPar
);
1264 ESelection
aSelAll( 0, 0, nLastPar
, nTxtLen
);
1266 pEngine
->TransliterateText( aSelAll
, nType
);
1268 if ( pEngine
->IsModified() )
1270 ScEditAttrTester
aTester( pEngine
.get() );
1271 if ( aTester
.NeedsObject() )
1273 // remove defaults (paragraph attributes) before creating text object
1274 SfxItemSet
* pEmpty
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
1275 pEngine
->SetDefaults( pEmpty
, true );
1277 // The cell will take ownership of the text object instance.
1278 SetEditText(ScAddress(nCol
,nRow
,nTab
), pEngine
->CreateTextObject());
1282 ScSetStringParam aParam
;
1283 aParam
.setTextInput();
1284 SetString(ScAddress(nCol
,nRow
,nTab
), pEngine
->GetText(), &aParam
);
1289 else if (aCell
.meType
== CELLTYPE_STRING
)
1291 OUString aOldStr
= aCell
.mpString
->getString();
1292 sal_Int32 nOldLen
= aOldStr
.getLength();
1294 if ( bConsiderLanguage
)
1296 SvtScriptType nScript
= GetStringScriptType( aOldStr
); //TODO: cell script type?
1297 sal_uInt16 nWhich
= ( nScript
== SvtScriptType::ASIAN
) ? ATTR_CJK_FONT_LANGUAGE
:
1298 ( ( nScript
== SvtScriptType::COMPLEX
) ? ATTR_CTL_FONT_LANGUAGE
:
1299 ATTR_FONT_LANGUAGE
);
1300 nLanguage
= static_cast<const SvxLanguageItem
*>(GetAttr( nCol
, nRow
, nTab
, nWhich
))->GetValue();
1303 uno::Sequence
<sal_Int32
> aOffsets
;
1304 OUString aNewStr
= aTransliterationWrapper
.transliterate( aOldStr
, nLanguage
, 0, nOldLen
, &aOffsets
);
1306 if ( aNewStr
!= aOldStr
)
1308 ScSetStringParam aParam
;
1309 aParam
.setTextInput();
1310 SetString(ScAddress(nCol
,nRow
,nTab
), aNewStr
, &aParam
);
1313 bFound
= GetNextMarkedCell( nCol
, nRow
, nTab
, rMultiMark
);
1318 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */