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 <editeng/autokernitem.hxx>
24 #include <editeng/fontitem.hxx>
25 #include <editeng/langitem.hxx>
26 #include <o3tl/unit_conversion.hxx>
27 #include <osl/thread.h>
28 #include <osl/diagnose.h>
29 #include <svl/asiancfg.hxx>
30 #include <svx/svditer.hxx>
31 #include <svx/svdograf.hxx>
32 #include <svx/svdoole2.hxx>
33 #include <svx/svdpage.hxx>
34 #include <svx/svdundo.hxx>
35 #include <svx/xtable.hxx>
36 #include <sfx2/printer.hxx>
38 #include <document.hxx>
39 #include <docoptio.hxx>
42 #include <drwlayer.hxx>
43 #include <markdata.hxx>
44 #include <patattr.hxx>
45 #include <rechead.hxx>
46 #include <poolhelp.hxx>
47 #include <docpool.hxx>
48 #include <stlpool.hxx>
49 #include <editutil.hxx>
50 #include <charthelper.hxx>
51 #include <conditio.hxx>
52 #include <documentlinkmgr.hxx>
54 using namespace ::com::sun::star
;
56 SfxBroadcaster
* ScDocument::GetDrawBroadcaster()
58 return mpDrawLayer
.get();
61 void ScDocument::BeginDrawUndo()
64 mpDrawLayer
->BeginCalcUndo(false);
67 void ScDocument::TransferDrawPage(const ScDocument
& rSrcDoc
, SCTAB nSrcPos
, SCTAB nDestPos
)
69 if (mpDrawLayer
&& rSrcDoc
.mpDrawLayer
)
71 SdrPage
* pOldPage
= rSrcDoc
.mpDrawLayer
->GetPage(static_cast<sal_uInt16
>(nSrcPos
));
72 SdrPage
* pNewPage
= mpDrawLayer
->GetPage(static_cast<sal_uInt16
>(nDestPos
));
74 if (pOldPage
&& pNewPage
)
76 SdrObjListIter
aIter( pOldPage
, SdrIterMode::Flat
);
77 SdrObject
* pOldObject
= aIter
.Next();
81 auto pStyleSheet
= pOldObject
->GetStyleSheet();
83 GetStyleSheetPool()->CopyStyleFrom(rSrcDoc
.GetStyleSheetPool(),
84 pStyleSheet
->GetName(), pStyleSheet
->GetFamily(), true);
86 // Clone to target SdrModel
87 rtl::Reference
<SdrObject
> pNewObject(pOldObject
->CloneSdrObject(*mpDrawLayer
));
88 pNewObject
->NbcMove(Size(0,0));
89 pNewPage
->InsertObject( pNewObject
.get() );
91 if (mpDrawLayer
->IsRecording())
92 mpDrawLayer
->AddCalcUndo( std::make_unique
<SdrUndoInsertObj
>( *pNewObject
) );
94 pOldObject
= aIter
.Next();
99 // make sure the data references of charts are adapted
100 // (this must be after InsertObject!)
101 ScChartHelper::AdjustRangesOfChartsOnDestinationPage( rSrcDoc
, *this, nSrcPos
, nDestPos
);
102 ScChartHelper::UpdateChartsOnDestinationPage(*this, nDestPos
);
105 void ScDocument::InitDrawLayer( ScDocShell
* pDocShell
)
107 if (pDocShell
&& !mpShell
)
109 ScMutationGuard
aGuard(*this, ScMutationGuardFlags::CORE
);
116 ScMutationGuard
aGuard(*this, ScMutationGuardFlags::CORE
);
118 if ( mpShell
&& !mpShell
->IsLoading() ) // don't call GetTitle while loading
119 aName
= mpShell
->GetTitle();
120 mpDrawLayer
.reset(new ScDrawLayer( this, aName
));
122 sfx2::LinkManager
* pMgr
= GetDocLinkManager().getLinkManager(bAutoCalc
);
124 mpDrawLayer
->SetLinkManager(pMgr
);
126 // set DrawingLayer's SfxItemPool at Calc's SfxItemPool as
127 // secondary pool to support DrawingLayer FillStyle ranges (and similar)
128 // in SfxItemSets using the Calc SfxItemPool. This is e.g. needed when
129 // the PageStyle using SvxBrushItem is visualized and will be potentially
130 // used more intense in the future
131 if (mxPoolHelper
.is() && !IsClipOrUndo()) //Using IsClipOrUndo as a proxy for SharePooledResources called
133 ScDocumentPool
* pLocalPool
= mxPoolHelper
->GetDocPool();
137 OSL_ENSURE(!pLocalPool
->GetSecondaryPool(), "OOps, already a secondary pool set where the DrawingLayer ItemPool is to be placed (!)");
138 pLocalPool
->SetSecondaryPool(&mpDrawLayer
->GetItemPool());
140 mpDrawLayer
->CreateDefaultStyles();
143 // Drawing pages are accessed by table number, so they must also be present
144 // for preceding table numbers, even if the tables aren't allocated
145 // (important for clipboard documents).
147 SCTAB nDrawPages
= 0;
149 for (nTab
= 0; nTab
< GetTableCount(); nTab
++)
151 nDrawPages
= nTab
+ 1; // needed number of pages
153 for (nTab
= 0; nTab
< nDrawPages
&& nTab
< GetTableCount(); nTab
++)
155 mpDrawLayer
->ScAddPage( nTab
); // always add page, with or without the table
158 OUString aTabName
= maTabs
[nTab
]->GetName();
159 mpDrawLayer
->ScRenamePage( nTab
, aTabName
);
161 maTabs
[nTab
]->SetDrawPageSize(false,false); // set the right size immediately
165 mpDrawLayer
->SetDefaultTabulator( GetDocOptions().GetTabDistance() );
169 // set draw defaults directly
170 SfxItemPool
& rDrawPool
= mpDrawLayer
->GetItemPool();
171 rDrawPool
.SetUserDefaultItem( SvxAutoKernItem( true, EE_CHAR_PAIRKERNING
) );
173 UpdateDrawLanguages();
175 mpDrawLayer
->EnableAdjust(false);
177 mpDrawLayer
->SetForbiddenCharsTable( xForbiddenCharacters
);
178 mpDrawLayer
->SetCharCompressType( GetAsianCompression() );
179 mpDrawLayer
->SetKernAsianPunctuation( GetAsianKerning() );
182 void ScDocument::UpdateDrawLanguages()
186 SfxItemPool
& rDrawPool
= mpDrawLayer
->GetItemPool();
187 rDrawPool
.SetUserDefaultItem( SvxLanguageItem( eLanguage
, EE_CHAR_LANGUAGE
) );
188 rDrawPool
.SetUserDefaultItem( SvxLanguageItem( eCjkLanguage
, EE_CHAR_LANGUAGE_CJK
) );
189 rDrawPool
.SetUserDefaultItem( SvxLanguageItem( eCtlLanguage
, EE_CHAR_LANGUAGE_CTL
) );
193 void ScDocument::UpdateDrawPrinter()
197 // use the printer even if IsValid is false
198 // Application::GetDefaultDevice causes trouble with changing MapModes
199 mpDrawLayer
->SetRefDevice(GetRefDevice());
203 void ScDocument::SetDrawPageSize(SCTAB nTab
)
205 if (ScTable
* pTable
= FetchTable(nTab
))
206 pTable
->SetDrawPageSize();
209 bool ScDocument::IsChart( const SdrObject
* pObject
)
211 // IsChart() implementation moved to svx drawinglayer
212 if(pObject
&& SdrObjKind::OLE2
== pObject
->GetObjIdentifier())
214 return static_cast<const SdrOle2Obj
*>(pObject
)->IsChart();
220 IMPL_LINK( ScDocument
, GetUserDefinedColor
, sal_uInt16
, nColorIndex
, Color
* )
222 rtl::Reference
<XColorList
> xColorList
;
224 xColorList
= mpDrawLayer
->GetColorList();
227 ScMutationGuard
aGuard(*this, ScMutationGuardFlags::CORE
);
228 if (!pColorList
.is())
229 pColorList
= XColorList::CreateStdColorList();
230 xColorList
= pColorList
;
232 return const_cast<Color
*>(&(xColorList
->GetColor(nColorIndex
)->GetColor()));
235 bool ScDocument::DrawGetPrintArea( ScRange
& rRange
, bool bSetHor
, bool bSetVer
) const
237 return mpDrawLayer
->GetPrintArea( rRange
, bSetHor
, bSetVer
);
240 void ScDocument::DeleteObjectsInArea( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
241 const ScMarkData
& rMark
, bool bAnchored
)
246 SCTAB nTabCount
= GetTableCount();
247 for (const auto& rTab
: rMark
)
249 if (rTab
>= nTabCount
)
252 mpDrawLayer
->DeleteObjectsInArea( rTab
, nCol1
, nRow1
, nCol2
, nRow2
, bAnchored
);
256 void ScDocument::DeleteObjectsInSelection( const ScMarkData
& rMark
)
261 mpDrawLayer
->DeleteObjectsInSelection( rMark
);
264 bool ScDocument::HasOLEObjectsInArea( const ScRange
& rRange
, const ScMarkData
* pTabMark
)
266 // pTabMark is used only for selected tables. If pTabMark is 0, all tables of rRange are used.
272 SCTAB nEndTab
= GetTableCount();
275 nStartTab
= rRange
.aStart
.Tab();
276 nEndTab
= rRange
.aEnd
.Tab();
279 for (SCTAB nTab
= nStartTab
; nTab
<= nEndTab
; nTab
++)
281 if ( !pTabMark
|| pTabMark
->GetTableSelect(nTab
) )
283 tools::Rectangle aMMRect
= GetMMRect( rRange
.aStart
.Col(), rRange
.aStart
.Row(),
284 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), nTab
);
286 SdrPage
* pPage
= mpDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
287 OSL_ENSURE(pPage
,"Page ?");
290 SdrObjListIter
aIter( pPage
, SdrIterMode::Flat
);
291 SdrObject
* pObject
= aIter
.Next();
294 if ( pObject
->GetObjIdentifier() == SdrObjKind::OLE2
&&
295 aMMRect
.Contains( pObject
->GetCurrentBoundRect() ) )
298 pObject
= aIter
.Next();
307 void ScDocument::StartAnimations( SCTAB nTab
)
311 SdrPage
* pPage
= mpDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
312 OSL_ENSURE(pPage
,"Page ?");
316 SdrObjListIter
aIter( pPage
, SdrIterMode::Flat
);
317 SdrObject
* pObject
= aIter
.Next();
320 if (SdrGrafObj
* pGrafObj
= dynamic_cast<SdrGrafObj
*>(pObject
))
322 if ( pGrafObj
->IsAnimated() )
324 pGrafObj
->StartAnimation();
327 pObject
= aIter
.Next();
331 bool ScDocument::HasBackgroundDraw( SCTAB nTab
, const tools::Rectangle
& rMMRect
) const
333 // Are there objects in the background layer who are (partly) affected by rMMRect
334 // (for Drawing optimization, no deletion in front of the background
337 SdrPage
* pPage
= mpDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
338 OSL_ENSURE(pPage
,"Page ?");
344 SdrObjListIter
aIter( pPage
, SdrIterMode::Flat
);
345 SdrObject
* pObject
= aIter
.Next();
346 while (pObject
&& !bFound
)
348 if ( pObject
->GetLayer() == SC_LAYER_BACK
&& pObject
->GetCurrentBoundRect().Overlaps( rMMRect
) )
350 pObject
= aIter
.Next();
356 bool ScDocument::HasAnyDraw( SCTAB nTab
, const tools::Rectangle
& rMMRect
) const
358 // Are there any objects at all who are (partly) affected by rMMRect?
359 // (To detect blank pages when printing)
362 SdrPage
* pPage
= mpDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
363 OSL_ENSURE(pPage
,"Page ?");
369 SdrObjListIter
aIter( pPage
, SdrIterMode::Flat
);
370 SdrObject
* pObject
= aIter
.Next();
371 while (pObject
&& !bFound
)
373 if ( pObject
->GetCurrentBoundRect().Overlaps( rMMRect
) )
375 pObject
= aIter
.Next();
381 void ScDocument::EnsureGraphicNames()
384 mpDrawLayer
->EnsureGraphicNames();
387 SdrObject
* ScDocument::GetObjectAtPoint( SCTAB nTab
, const Point
& rPos
)
389 // for Drag&Drop on draw object
390 SdrObject
* pFound
= nullptr;
391 if (mpDrawLayer
&& nTab
< GetTableCount() && maTabs
[nTab
])
393 SdrPage
* pPage
= mpDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
394 OSL_ENSURE(pPage
,"Page ?");
397 SdrObjListIter
aIter( pPage
, SdrIterMode::Flat
);
398 SdrObject
* pObject
= aIter
.Next();
401 if ( pObject
->GetCurrentBoundRect().Contains(rPos
) )
403 // Intern is of no interest
404 // Only object form background layer, when no object form another layer is found
405 SdrLayerID nLayer
= pObject
->GetLayer();
406 if ( (nLayer
!= SC_LAYER_INTERN
) && (nLayer
!= SC_LAYER_HIDDEN
) )
408 if ( nLayer
!= SC_LAYER_BACK
||
409 !pFound
|| pFound
->GetLayer() == SC_LAYER_BACK
)
415 // Continue search -> take last (on top) found object
416 pObject
= aIter
.Next();
423 bool ScDocument::IsPrintEmpty( SCCOL nStartCol
, SCROW nStartRow
,
424 SCCOL nEndCol
, SCROW nEndRow
,
425 SCTAB nTab
, bool bLeftIsEmpty
,
426 ScRange
* pLastRange
, tools::Rectangle
* pLastMM
) const
428 if (!IsBlockEmpty( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
))
431 if (HasAttrib(ScRange(nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
), HasAttrFlags::Lines
))
432 // We want to print sheets with borders even if there is no cell content.
435 tools::Rectangle aMMRect
;
436 if ( pLastRange
&& pLastMM
&& nTab
== pLastRange
->aStart
.Tab() &&
437 nStartRow
== pLastRange
->aStart
.Row() && nEndRow
== pLastRange
->aEnd
.Row() )
439 // keep vertical part of aMMRect, only update horizontal position
442 tools::Long nLeft
= GetColWidth(0, nStartCol
-1, nTab
);
443 tools::Long nRight
= nLeft
+ GetColWidth(nStartCol
,nEndCol
, nTab
);
445 aMMRect
.SetLeft(o3tl::convert(nLeft
, o3tl::Length::twip
, o3tl::Length::mm100
));
446 aMMRect
.SetRight(o3tl::convert(nRight
, o3tl::Length::twip
, o3tl::Length::mm100
));
449 aMMRect
= GetMMRect( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
);
451 if ( pLastRange
&& pLastMM
)
453 *pLastRange
= ScRange( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
);
457 if ( HasAnyDraw( nTab
, aMMRect
))
460 if ( nStartCol
> 0 && !bLeftIsEmpty
)
462 // similar to in ScPrintFunc::AdjustPrintArea
463 // ExtendPrintArea starting only from the start column of the print area
465 SCCOL nExtendCol
= nStartCol
- 1;
466 SCROW nTmpRow
= nEndRow
;
468 // ExtendMerge() is non-const, but called without refresh. GetPrinter()
469 // might create and assign a printer.
470 ScDocument
* pThis
= const_cast<ScDocument
*>(this);
472 pThis
->ExtendMerge( 0,nStartRow
, nExtendCol
,nTmpRow
, nTab
); // no Refresh, incl. Attrs
474 OutputDevice
* pDev
= pThis
->GetPrinter();
475 pDev
->SetMapMode(MapMode(MapUnit::MapPixel
)); // Important for GetNeededSize
476 ExtendPrintArea( pDev
, nTab
, 0, nStartRow
, nExtendCol
, nEndRow
);
477 if ( nExtendCol
>= nStartCol
)
484 void ScDocument::Clear( bool bFromDestructor
)
486 for (auto& rxTab
: maTabs
)
488 rxTab
->GetCondFormList()->clear();
491 pSelectionAttr
.reset();
495 mpDrawLayer
->ClearModel( bFromDestructor
);
499 bool ScDocument::HasDetectiveObjects(SCTAB nTab
) const
501 // looks for detective objects, annotations don't count
502 // (used to adjust scale so detective objects hit their cells better)
508 SdrPage
* pPage
= mpDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
509 OSL_ENSURE(pPage
,"Page ?");
512 SdrObjListIter
aIter( pPage
, SdrIterMode::DeepNoGroups
);
513 SdrObject
* pObject
= aIter
.Next();
514 while (pObject
&& !bFound
)
516 // anything on the internal layer except captions (annotations)
517 if ( (pObject
->GetLayer() == SC_LAYER_INTERN
) && !ScDrawLayer::IsNoteCaption( pObject
) )
520 pObject
= aIter
.Next();
528 void ScDocument::UpdateFontCharSet()
530 // In old versions (until 4.0 without SP), when switching between systems,
531 // the Font attribute was not adjusted.
532 // This has to be redone for Documents until SP2:
533 // Everything that is not SYMBOL is set to system CharSet.
534 // CharSet should be correct for new documents (version SC_FONTCHARSET)
536 bool bUpdateOld
= ( nSrcVer
< SC_FONTCHARSET
);
538 rtl_TextEncoding eSysSet
= osl_getThreadTextEncoding();
539 if ( !(eSrcSet
!= eSysSet
|| bUpdateOld
) )
542 ScDocumentPool
* pPool
= mxPoolHelper
->GetDocPool();
544 pPool
->iterateItemSurrogates(ATTR_FONT
, [&](SfxItemPool::SurrogateData
& rData
)
546 const SvxFontItem
& rSvxFontItem(static_cast<const SvxFontItem
&>(rData
.getItem()));
547 if (eSrcSet
== rSvxFontItem
.GetCharSet() || (bUpdateOld
&& RTL_TEXTENCODING_SYMBOL
!= rSvxFontItem
.GetCharSet()))
549 SvxFontItem
* pNew(rSvxFontItem
.Clone(pPool
));
550 pNew
->SetCharSet(eSysSet
);
551 rData
.setItem(std::unique_ptr
<SfxPoolItem
>(pNew
));
553 return true; // continue callbacks
558 pPool
->iterateItemSurrogates(EE_CHAR_FONTINFO
, [&](SfxItemPool::SurrogateData
& rData
)
560 const SvxFontItem
& rSvxFontItem(static_cast<const SvxFontItem
&>(rData
.getItem()));
561 if (eSrcSet
== rSvxFontItem
.GetCharSet() || (bUpdateOld
&& RTL_TEXTENCODING_SYMBOL
!= rSvxFontItem
.GetCharSet()))
563 SvxFontItem
* pNew(rSvxFontItem
.Clone(pPool
));
564 pNew
->SetCharSet(eSysSet
);
565 rData
.setItem(std::unique_ptr
<SfxPoolItem
>(pNew
));
567 return true; // continue callbacks
572 void ScDocument::SetLoadingMedium( bool bVal
)
574 bLoadingMedium
= bVal
;
575 for (auto& rxTab
: maTabs
)
580 rxTab
->SetLoadingMedium(bVal
);
584 void ScDocument::SetImportingXML( bool bVal
)
586 bImportingXML
= bVal
;
588 mpDrawLayer
->EnableAdjust(!bImportingXML
);
592 // #i57869# after loading, do the real RTL mirroring for the sheets that have the LoadingRTL flag set
594 for (SCTAB nTab
= 0; nTab
< GetTableCount() && maTabs
[nTab
]; nTab
++)
595 if ( maTabs
[nTab
]->IsLoadingRTL() )
597 // SetLayoutRTL => SetDrawPageSize => ScDrawLayer::SetPageSize, includes RTL-mirroring;
598 // bImportingXML must be cleared first
599 maTabs
[nTab
]->SetLoadingRTL( false );
600 SetLayoutRTL( nTab
, true, ScObjectHandling::MoveRTLMode
);
604 SetLoadingMedium(bVal
);
607 const std::shared_ptr
<SvxForbiddenCharactersTable
>& ScDocument::GetForbiddenCharacters() const
609 return xForbiddenCharacters
;
612 void ScDocument::SetForbiddenCharacters(const std::shared_ptr
<SvxForbiddenCharactersTable
>& rNew
)
614 xForbiddenCharacters
= rNew
;
616 EditEngine::SetForbiddenCharsTable( xForbiddenCharacters
);
618 mpDrawLayer
->SetForbiddenCharsTable( xForbiddenCharacters
);
621 bool ScDocument::IsValidAsianCompression() const
623 return nAsianCompression
!= CharCompressType::Invalid
;
626 CharCompressType
ScDocument::GetAsianCompression() const
628 if ( nAsianCompression
== CharCompressType::Invalid
)
629 return CharCompressType::NONE
;
631 return nAsianCompression
;
634 void ScDocument::SetAsianCompression(CharCompressType nNew
)
636 nAsianCompression
= nNew
;
638 mpEditEngine
->SetAsianCompressionMode( nAsianCompression
);
640 mpDrawLayer
->SetCharCompressType( nAsianCompression
);
643 bool ScDocument::IsValidAsianKerning() const
645 return ( nAsianKerning
!= SC_ASIANKERNING_INVALID
);
648 bool ScDocument::GetAsianKerning() const
650 if ( nAsianKerning
== SC_ASIANKERNING_INVALID
)
653 return static_cast<bool>(nAsianKerning
);
656 void ScDocument::SetAsianKerning(bool bNew
)
658 nAsianKerning
= static_cast<sal_uInt8
>(bNew
);
660 mpEditEngine
->SetKernAsianPunctuation( static_cast<bool>( nAsianKerning
) );
662 mpDrawLayer
->SetKernAsianPunctuation( static_cast<bool>( nAsianKerning
) );
665 void ScDocument::ApplyAsianEditSettings( ScEditEngineDefaulter
& rEngine
)
667 EditEngine::SetForbiddenCharsTable( xForbiddenCharacters
);
668 rEngine
.SetAsianCompressionMode( GetAsianCompression() );
669 rEngine
.SetKernAsianPunctuation( GetAsianKerning() );
672 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */