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"
22 #include <svx/pageitem.hxx>
23 #include <sfx2/linkmgr.hxx>
27 #include "stlsheet.hxx"
28 #include "stlpool.hxx"
30 #include "viewdata.hxx"
31 #include "tabvwsh.hxx"
32 #include "tablink.hxx"
33 #include "globstr.hrc"
35 #include "compiler.hxx"
36 #include "interpre.hxx"
37 #include "calcconfig.hxx"
39 #include <vcl/msgbox.hxx>
48 SfxStyleSheetBase
*pSource
;
49 SfxStyleSheetBase
*pDest
;
56 void ScDocShell::SetVisArea( const Rectangle
& rVisArea
)
58 // with the SnapVisArea call in SetVisAreaOrSize, it's safe to always
59 // use both the size and position of the VisArea
60 SetVisAreaOrSize( rVisArea
);
63 static void lcl_SetTopRight( Rectangle
& rRect
, const Point
& rPos
)
65 Size aSize
= rRect
.GetSize();
66 rRect
.Right() = rPos
.X();
67 rRect
.Left() = rPos
.X() - aSize
.Width() + 1;
68 rRect
.Top() = rPos
.Y();
69 rRect
.Bottom() = rPos
.Y() + aSize
.Height() - 1;
72 void ScDocShell::SetVisAreaOrSize( const Rectangle
& rVisArea
)
74 bool bNegativePage
= aDocument
.IsNegativePage( aDocument
.GetVisibleTab() );
76 Rectangle aArea
= rVisArea
;
77 // when loading, don't check for negative values, because the sheet orientation
79 if ( !aDocument
.IsImportingXML() )
81 if ( ( bNegativePage
? (aArea
.Right() > 0) : (aArea
.Left() < 0) ) || aArea
.Top() < 0 )
83 // VisArea start position can't be negative.
84 // Move the VisArea, otherwise only the upper left position would
85 // be changed in SnapVisArea, and the size would be wrong.
87 Point
aNewPos( 0, std::max( aArea
.Top(), (long) 0 ) );
90 aNewPos
.X() = std::min( aArea
.Right(), (long) 0 );
91 lcl_SetTopRight( aArea
, aNewPos
);
95 aNewPos
.X() = std::max( aArea
.Left(), (long) 0 );
96 aArea
.SetPos( aNewPos
);
101 // hier Position anpassen!
103 // when loading an ole object, the VisArea is set from the document's
104 // view settings and must be used as-is (document content may not be complete yet).
105 if ( !aDocument
.IsImportingXML() )
106 SnapVisArea( aArea
);
108 //TODO/LATER: it's unclear which IPEnv is used here
110 SvInPlaceEnvironment* pEnv = GetIPEnv();
113 vcl::Window* pWin = pEnv->GetEditWin();
114 pEnv->MakeScale( aArea.GetSize(), MAP_100TH_MM,
115 pWin->LogicToPixel( aArea.GetSize() ) );
118 //TODO/LATER: formerly in SvInplaceObject
119 SfxObjectShell::SetVisArea( aArea
);
121 if (bIsInplace
) // Zoom in der InPlace View einstellen
123 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
126 if (pViewSh
->GetViewData().GetDocShell() == this)
127 pViewSh
->UpdateOleZoom();
131 if (aDocument
.IsEmbedded())
134 aDocument
.GetEmbedded( aOld
);
135 aDocument
.SetEmbedded( aDocument
.GetVisibleTab(), aArea
);
137 aDocument
.GetEmbedded( aNew
);
139 PostPaint(0,0,0,MAXCOL
,MAXROW
,MAXTAB
,PAINT_GRID
);
141 //TODO/LATER: currently not implemented
142 //ViewChanged( ASPECT_CONTENT ); // auch im Container anzeigen
146 bool ScDocShell::IsOle()
148 return (GetCreateMode() == SfxObjectCreateMode::EMBEDDED
);
151 void ScDocShell::UpdateOle( const ScViewData
* pViewData
, bool bSnapSize
)
153 // wenn's gar nicht Ole ist, kann man sich die Berechnungen sparen
154 // (VisArea wird dann beim Save wieder zurueckgesetzt)
156 if (GetCreateMode() == SfxObjectCreateMode::STANDARD
)
159 OSL_ENSURE(pViewData
,"pViewData==0 bei ScDocShell::UpdateOle");
161 Rectangle aOldArea
= SfxObjectShell::GetVisArea();
162 Rectangle aNewArea
= aOldArea
;
164 bool bEmbedded
= aDocument
.IsEmbedded();
166 aNewArea
= aDocument
.GetEmbeddedRect();
169 SCTAB nTab
= pViewData
->GetTabNo();
170 if ( nTab
!= aDocument
.GetVisibleTab() )
171 aDocument
.SetVisibleTab( nTab
);
173 bool bNegativePage
= aDocument
.IsNegativePage( nTab
);
174 SCCOL nX
= pViewData
->GetPosX(SC_SPLIT_LEFT
);
175 SCROW nY
= pViewData
->GetPosY(SC_SPLIT_BOTTOM
);
176 Rectangle aMMRect
= aDocument
.GetMMRect( nX
,nY
, nX
,nY
, nTab
);
178 lcl_SetTopRight( aNewArea
, aMMRect
.TopRight() );
180 aNewArea
.SetPos( aMMRect
.TopLeft() );
182 SnapVisArea(aNewArea
); // uses the new VisibleTab
185 if (aNewArea
!= aOldArea
)
186 SetVisAreaOrSize( aNewArea
); // hier muss auch der Start angepasst werden
189 // Style-Krempel fuer Organizer etc.
191 SfxStyleSheetBasePool
* ScDocShell::GetStyleSheetPool()
193 return static_cast<SfxStyleSheetBasePool
*>(aDocument
.GetStyleSheetPool());
196 // nach dem Laden von Vorlagen aus einem anderen Dokment (LoadStyles, Insert)
197 // muessen die SetItems (ATTR_PAGE_HEADERSET, ATTR_PAGE_FOOTERSET) auf den richtigen
198 // Pool umgesetzt werden, bevor der Quell-Pool geloescht wird.
200 static void lcl_AdjustPool( SfxStyleSheetBasePool
* pStylePool
)
202 pStylePool
->SetSearchMask(SfxStyleFamily::Page
);
203 SfxStyleSheetBase
*pStyle
= pStylePool
->First();
206 SfxItemSet
& rStyleSet
= pStyle
->GetItemSet();
208 const SfxPoolItem
* pItem
;
209 if (rStyleSet
.GetItemState(ATTR_PAGE_HEADERSET
,false,&pItem
) == SfxItemState::SET
)
211 const SfxItemSet
& rSrcSet
= static_cast<const SvxSetItem
*>(pItem
)->GetItemSet();
212 SfxItemSet
* pDestSet
= new SfxItemSet(*rStyleSet
.GetPool(),rSrcSet
.GetRanges());
213 pDestSet
->Put(rSrcSet
);
214 rStyleSet
.Put(SvxSetItem(ATTR_PAGE_HEADERSET
,pDestSet
));
216 if (rStyleSet
.GetItemState(ATTR_PAGE_FOOTERSET
,false,&pItem
) == SfxItemState::SET
)
218 const SfxItemSet
& rSrcSet
= static_cast<const SvxSetItem
*>(pItem
)->GetItemSet();
219 SfxItemSet
* pDestSet
= new SfxItemSet(*rStyleSet
.GetPool(),rSrcSet
.GetRanges());
220 pDestSet
->Put(rSrcSet
);
221 rStyleSet
.Put(SvxSetItem(ATTR_PAGE_FOOTERSET
,pDestSet
));
224 pStyle
= pStylePool
->Next();
228 void ScDocShell::LoadStyles( SfxObjectShell
&rSource
)
230 aDocument
.StylesToNames();
232 SfxObjectShell::LoadStyles(rSource
);
233 lcl_AdjustPool( GetStyleSheetPool() ); // SetItems anpassen
235 aDocument
.UpdStlShtPtrsFrmNms();
237 UpdateAllRowHeights();
241 PostPaint( 0,0,0, MAXCOL
,MAXROW
,MAXTAB
, PAINT_GRID
| PAINT_LEFT
);
244 void ScDocShell::LoadStylesArgs( ScDocShell
& rSource
, bool bReplace
, bool bCellStyles
, bool bPageStyles
)
246 // similar to LoadStyles, but with selectable behavior for XStyleLoader::loadStylesFromURL call
248 if ( !bCellStyles
&& !bPageStyles
) // nothing to do
251 ScStyleSheetPool
* pSourcePool
= rSource
.GetDocument().GetStyleSheetPool();
252 ScStyleSheetPool
* pDestPool
= aDocument
.GetStyleSheetPool();
254 SfxStyleFamily eFamily
= bCellStyles
?
255 ( bPageStyles
? SfxStyleFamily::All
: SfxStyleFamily::Para
) :
256 SfxStyleFamily::Page
;
257 SfxStyleSheetIterator
aIter( pSourcePool
, eFamily
);
258 sal_uInt16 nSourceCount
= aIter
.Count();
259 if ( nSourceCount
== 0 )
260 return; // no source styles
262 std::unique_ptr
<ScStylePair
[]> pStyles(new ScStylePair
[ nSourceCount
]);
263 sal_uInt16 nFound
= 0;
265 // first create all new styles
267 SfxStyleSheetBase
* pSourceStyle
= aIter
.First();
270 OUString aName
= pSourceStyle
->GetName();
271 SfxStyleSheetBase
* pDestStyle
= pDestPool
->Find( pSourceStyle
->GetName(), pSourceStyle
->GetFamily() );
274 // touch existing styles only if replace flag is set
277 pStyles
[nFound
].pSource
= pSourceStyle
;
278 pStyles
[nFound
].pDest
= pDestStyle
;
284 pStyles
[nFound
].pSource
= pSourceStyle
;
285 pStyles
[nFound
].pDest
= &pDestPool
->Make( aName
, pSourceStyle
->GetFamily(), pSourceStyle
->GetMask() );
289 pSourceStyle
= aIter
.Next();
292 // then copy contents (after inserting all styles, for parent etc.)
294 for ( sal_uInt16 i
= 0; i
< nFound
; ++i
)
296 pStyles
[i
].pDest
->GetItemSet().PutExtended(
297 pStyles
[i
].pSource
->GetItemSet(), SfxItemState::DONTCARE
, SfxItemState::DEFAULT
);
298 if(pStyles
[i
].pSource
->HasParentSupport())
299 pStyles
[i
].pDest
->SetParent(pStyles
[i
].pSource
->GetParent());
300 // follow is never used
303 lcl_AdjustPool( GetStyleSheetPool() ); // adjust SetItems
304 UpdateAllRowHeights();
305 PostPaint( 0,0,0, MAXCOL
,MAXROW
,MAXTAB
, PAINT_GRID
| PAINT_LEFT
); // Paint
308 void ScDocShell::ReconnectDdeLink(SfxObjectShell
& rServer
)
310 ::sfx2::LinkManager
* pLinkManager
= aDocument
.GetLinkManager();
314 pLinkManager
->ReconnectDdeLink(rServer
);
317 void ScDocShell::UpdateLinks()
319 typedef std::unordered_set
<OUString
, OUStringHash
> StrSetType
;
321 sfx2::LinkManager
* pLinkManager
= aDocument
.GetLinkManager();
324 // nicht mehr benutzte Links raus
326 size_t nCount
= pLinkManager
->GetLinks().size();
327 for (size_t k
=nCount
; k
>0; )
330 ::sfx2::SvBaseLink
* pBase
= pLinkManager
->GetLinks()[k
].get();
331 if (ScTableLink
* pTabLink
= dynamic_cast<ScTableLink
*>(pBase
))
333 if (pTabLink
->IsUsed())
334 aNames
.insert(pTabLink
->GetFileName());
335 else // nicht mehr benutzt -> loeschen
337 pTabLink
->SetAddUndo(true);
338 pLinkManager
->Remove(k
);
343 // neue Links eintragen
345 SCTAB nTabCount
= aDocument
.GetTableCount();
346 for (SCTAB i
= 0; i
< nTabCount
; ++i
)
348 if (!aDocument
.IsLinked(i
))
351 OUString aDocName
= aDocument
.GetLinkDoc(i
);
352 OUString aFltName
= aDocument
.GetLinkFlt(i
);
353 OUString aOptions
= aDocument
.GetLinkOpt(i
);
354 sal_uLong nRefresh
= aDocument
.GetLinkRefreshDelay(i
);
356 for (SCTAB j
= 0; j
< i
&& !bThere
; ++j
) // im Dokument mehrfach?
358 if (aDocument
.IsLinked(j
)
359 && aDocument
.GetLinkDoc(j
) == aDocName
360 && aDocument
.GetLinkFlt(j
) == aFltName
361 && aDocument
.GetLinkOpt(j
) == aOptions
)
362 // Ignore refresh delay in compare, it should be the
363 // same for identical links and we don't want dupes
368 if (!bThere
) // schon als Filter eingetragen?
370 if (!aNames
.insert(aDocName
).second
)
376 ScTableLink
* pLink
= new ScTableLink( this, aDocName
, aFltName
, aOptions
, nRefresh
);
377 pLink
->SetInCreate(true);
378 pLinkManager
->InsertFileLink(*pLink
, OBJECT_CLIENT_FILE
, aDocName
, &aFltName
);
380 pLink
->SetInCreate(false);
385 void ScDocShell::ReloadTabLinks()
387 sfx2::LinkManager
* pLinkManager
= aDocument
.GetLinkManager();
390 size_t nCount
= pLinkManager
->GetLinks().size();
391 for (size_t i
=0; i
<nCount
; i
++ )
393 ::sfx2::SvBaseLink
* pBase
= pLinkManager
->GetLinks()[i
].get();
394 if (ScTableLink
* pTabLink
= dynamic_cast<ScTableLink
*>(pBase
))
396 // pTabLink->SetAddUndo(sal_False); //! Undo's zusammenfassen
398 // Painting only after Update() makes no sense:
399 // ScTableLink::Refresh() will post a Paint only is bDoPaint is true
400 // pTabLink->SetPaint(false); // Paint nur einmal am Ende
402 //pTabLink->SetPaint(true);
403 // pTabLink->SetAddUndo(sal_True);
411 PostPaint( ScRange(0,0,0,MAXCOL
,MAXROW
,MAXTAB
),
412 PAINT_GRID
| PAINT_TOP
| PAINT_LEFT
);
414 SetDocumentModified();
418 void ScDocShell::SetFormulaOptions( const ScFormulaOptions
& rOpt
, bool bForLoading
)
420 aDocument
.SetGrammar( rOpt
.GetFormulaSyntax() );
422 // This is nasty because it resets module globals from within a docshell!
423 // For actual damage caused see fdo#82183 where an unconditional
424 // ScGlobal::ResetFunctionList() (without checking GetUseEnglishFuncName())
425 // lead to a crash because the function list was still used by the Formula
426 // Wizard when loading the second document.
427 // Do the stupid stuff only when we're not called while loading a document.
429 /* TODO: bForLoading is a workaround, rather get rid of setting any
430 * globals from per document instances like ScDocShell. */
432 /* XXX this is utter crap, we rely on the options being set here at least
433 * once, for the very first document, empty or loaded. */
434 static bool bInitOnce
= true;
436 if (!bForLoading
|| bInitOnce
)
438 bool bForceInit
= bInitOnce
;
440 if (bForceInit
|| rOpt
.GetUseEnglishFuncName() != SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName())
442 // This needs to be called first since it may re-initialize the entire
444 if (rOpt
.GetUseEnglishFuncName())
446 // switch native symbols to English.
447 ScCompiler
aComp(nullptr, ScAddress());
448 ScCompiler::OpCodeMapPtr xMap
= aComp
.GetOpCodeMap(css::sheet::FormulaLanguage::ENGLISH
);
449 ScCompiler::SetNativeSymbols(xMap
);
452 // re-initialize native symbols with localized function names.
453 ScCompiler::ResetNativeSymbols();
455 // Force re-population of function names for the function wizard, function tip etc.
456 ScGlobal::ResetFunctionList();
459 // Update the separators.
460 ScCompiler::UpdateSeparatorsNative(
461 rOpt
.GetFormulaSepArg(), rOpt
.GetFormulaSepArrayCol(), rOpt
.GetFormulaSepArrayRow());
463 // Global interpreter settings.
464 ScInterpreter::SetGlobalConfig(rOpt
.GetCalcConfig());
467 // Per document interpreter settings.
468 SetCalcConfig( rOpt
.GetCalcConfig());
471 void ScDocShell::SetCalcConfig( const ScCalcConfig
& rConfig
)
473 aDocument
.SetCalcConfig( rConfig
);
476 void ScDocShell::CheckConfigOptions()
478 if (IsConfigOptionsChecked())
479 // no need to check repeatedly.
482 OUString aDecSep
= ScGlobal::GetpLocaleData()->getNumDecimalSep();
484 ScModule
* pScMod
= SC_MOD();
485 const ScFormulaOptions
& rOpt
=pScMod
->GetFormulaOptions();
486 const OUString
& aSepArg
= rOpt
.GetFormulaSepArg();
487 const OUString
& aSepArrRow
= rOpt
.GetFormulaSepArrayRow();
488 const OUString
& aSepArrCol
= rOpt
.GetFormulaSepArrayCol();
490 if (aDecSep
== aSepArg
|| aDecSep
== aSepArrRow
|| aDecSep
== aSepArrCol
)
492 // One of arg separators conflicts with the current decimal
493 // separator. Reset them to default.
494 ScFormulaOptions aNew
= rOpt
;
495 aNew
.ResetFormulaSeparators();
496 SetFormulaOptions(aNew
);
497 pScMod
->SetFormulaOptions(aNew
);
499 // Launch a nice warning dialog to let the users know of this change.
500 ScTabViewShell
* pViewShell
= GetBestViewShell();
503 vcl::Window
* pParent
= pViewShell
->GetFrameWin();
504 ScopedVclPtrInstance
< InfoBox
> aBox(pParent
, ScGlobal::GetRscString(STR_OPTIONS_WARN_SEPARATORS
));
508 // For now, this is the only option setting that could launch info
509 // dialog. But in the future we may want to implement a nicer
510 // dialog to display a list of warnings in case we have several
511 // pieces of information to display.
514 SetConfigOptionsChecked(true);
517 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */