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 <sot/exchange.hxx>
24 #include <editeng/autokernitem.hxx>
25 #include <editeng/fontitem.hxx>
26 #include <editeng/forbiddencharacterstable.hxx>
27 #include <editeng/langitem.hxx>
28 #include <osl/thread.h>
29 #include <svx/svdetc.hxx>
30 #include <svx/svditer.hxx>
31 #include <svx/svdocapt.hxx>
32 #include <svx/svdograf.hxx>
33 #include <svx/svdoole2.hxx>
34 #include <svx/svdouno.hxx>
35 #include <svx/svdpage.hxx>
36 #include <svx/svdundo.hxx>
37 #include <svx/xtable.hxx>
38 #include <sfx2/objsh.hxx>
39 #include <sfx2/printer.hxx>
40 #include <unotools/saveopt.hxx>
41 #include <unotools/pathoptions.hxx>
43 #include "document.hxx"
44 #include "docoptio.hxx"
46 #include "drwlayer.hxx"
47 #include "markdata.hxx"
48 #include "patattr.hxx"
49 #include "rechead.hxx"
50 #include "poolhelp.hxx"
51 #include "docpool.hxx"
52 #include "detfunc.hxx"
53 #include "editutil.hxx"
55 #include "charthelper.hxx"
56 #include "interpre.hxx"
58 using namespace ::com::sun::star
;
60 // -----------------------------------------------------------------------
63 SfxBroadcaster
* ScDocument::GetDrawBroadcaster()
68 void ScDocument::BeginDrawUndo()
71 pDrawLayer
->BeginCalcUndo(false);
74 rtl::Reference
<XColorList
> ScDocument::GetColorList()
77 return pDrawLayer
->GetColorList();
81 pColorList
= XColorList::CreateStdColorList();
86 void ScDocument::TransferDrawPage(ScDocument
* pSrcDoc
, SCTAB nSrcPos
, SCTAB nDestPos
)
88 if (pDrawLayer
&& pSrcDoc
->pDrawLayer
)
90 SdrPage
* pOldPage
= pSrcDoc
->pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nSrcPos
));
91 SdrPage
* pNewPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nDestPos
));
93 if (pOldPage
&& pNewPage
)
95 SdrObjListIter
aIter( *pOldPage
, IM_FLAT
);
96 SdrObject
* pOldObject
= aIter
.Next();
100 SdrObject
* pNewObject
= pOldObject
->Clone();
101 // SdrObject* pNewObject = pOldObject->Clone( pNewPage, pDrawLayer );
102 pNewObject
->SetModel(pDrawLayer
);
103 pNewObject
->SetPage(pNewPage
);
105 pNewObject
->NbcMove(Size(0,0));
106 pNewPage
->InsertObject( pNewObject
);
108 if (pDrawLayer
->IsRecording())
109 pDrawLayer
->AddCalcUndo( new SdrUndoInsertObj( *pNewObject
) );
111 pOldObject
= aIter
.Next();
116 // make sure the data references of charts are adapted
117 // (this must be after InsertObject!)
118 ScChartHelper::AdjustRangesOfChartsOnDestinationPage( pSrcDoc
, this, nSrcPos
, nDestPos
);
119 ScChartHelper::UpdateChartsOnDestinationPage(this, nDestPos
);
122 void ScDocument::InitDrawLayer( SfxObjectShell
* pDocShell
)
124 if (pDocShell
&& !pShell
)
130 if ( pShell
&& !pShell
->IsLoading() ) // don't call GetTitle while loading
131 aName
= pShell
->GetTitle();
132 pDrawLayer
= new ScDrawLayer( this, aName
);
133 if (GetLinkManager())
134 pDrawLayer
->SetLinkManager( pLinkManager
);
136 // Drawing pages are accessed by table number, so they must also be present
137 // for preceding table numbers, even if the tables aren't allocated
138 // (important for clipboard documents).
140 SCTAB nDrawPages
= 0;
142 for (nTab
=0; nTab
< static_cast<SCTAB
>(maTabs
.size()); nTab
++)
144 nDrawPages
= nTab
+ 1; // needed number of pages
146 for (nTab
=0; nTab
<nDrawPages
&& nTab
< static_cast<SCTAB
>(maTabs
.size()); nTab
++)
148 pDrawLayer
->ScAddPage( nTab
); // always add page, with or without the table
152 maTabs
[nTab
]->GetName(aTabName
);
153 pDrawLayer
->ScRenamePage( nTab
, aTabName
);
155 maTabs
[nTab
]->SetDrawPageSize(false,false); // set the right size immediately
159 pDrawLayer
->SetDefaultTabulator( GetDocOptions().GetTabDistance() );
163 // set draw defaults directly
164 SfxItemPool
& rDrawPool
= pDrawLayer
->GetItemPool();
165 rDrawPool
.SetPoolDefaultItem( SvxAutoKernItem( sal_True
, EE_CHAR_PAIRKERNING
) );
167 UpdateDrawLanguages();
169 pDrawLayer
->EnableAdjust(false);
171 pDrawLayer
->SetForbiddenCharsTable( xForbiddenCharacters
);
172 pDrawLayer
->SetCharCompressType( GetAsianCompression() );
173 pDrawLayer
->SetKernAsianPunctuation( GetAsianKerning() );
177 void ScDocument::UpdateDrawLanguages()
181 SfxItemPool
& rDrawPool
= pDrawLayer
->GetItemPool();
182 rDrawPool
.SetPoolDefaultItem( SvxLanguageItem( eLanguage
, EE_CHAR_LANGUAGE
) );
183 rDrawPool
.SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage
, EE_CHAR_LANGUAGE_CJK
) );
184 rDrawPool
.SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage
, EE_CHAR_LANGUAGE_CTL
) );
188 void ScDocument::UpdateDrawPrinter()
192 // use the printer even if IsValid is false
193 // Application::GetDefaultDevice causes trouble with changing MapModes
194 pDrawLayer
->SetRefDevice(GetRefDevice());
198 void ScDocument::SetDrawPageSize(SCTAB nTab
)
200 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
203 maTabs
[nTab
]->SetDrawPageSize();
206 bool ScDocument::IsChart( const SdrObject
* pObject
)
209 // IsChart() implementation moved to svx drawinglayer
210 if(pObject
&& OBJ_OLE2
== pObject
->GetObjIdentifier())
212 return ((SdrOle2Obj
*)pObject
)->IsChart();
218 IMPL_LINK_INLINE_START( ScDocument
, GetUserDefinedColor
, sal_uInt16
*, pColorIndex
)
220 return (sal_IntPtr
) &((GetColorList()->GetColor(*pColorIndex
))->GetColor());
222 IMPL_LINK_INLINE_END( ScDocument
, GetUserDefinedColor
, sal_uInt16
*, pColorIndex
)
224 void ScDocument::DeleteDrawLayer()
229 bool ScDocument::DrawGetPrintArea( ScRange
& rRange
, bool bSetHor
, bool bSetVer
) const
231 return pDrawLayer
->GetPrintArea( rRange
, bSetHor
, bSetVer
);
234 void ScDocument::DrawMovePage( sal_uInt16 nOldPos
, sal_uInt16 nNewPos
)
236 pDrawLayer
->ScMovePage(nOldPos
,nNewPos
);
239 void ScDocument::DrawCopyPage( sal_uInt16 nOldPos
, sal_uInt16 nNewPos
)
241 // angelegt wird die Page schon im ScTable ctor
242 pDrawLayer
->ScCopyPage( nOldPos
, nNewPos
, false );
245 void ScDocument::DeleteObjectsInArea( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
246 const ScMarkData
& rMark
)
251 SCTAB nTabCount
= GetTableCount();
252 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
253 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
255 pDrawLayer
->DeleteObjectsInArea( *itr
, nCol1
, nRow1
, nCol2
, nRow2
);
258 void ScDocument::DeleteObjectsInSelection( const ScMarkData
& rMark
)
263 pDrawLayer
->DeleteObjectsInSelection( rMark
);
266 bool ScDocument::HasOLEObjectsInArea( const ScRange
& rRange
, const ScMarkData
* pTabMark
)
268 // pTabMark is used only for selected tables. If pTabMark is 0, all tables of rRange are used.
274 SCTAB nEndTab
= static_cast<SCTAB
>(maTabs
.size());
277 nStartTab
= rRange
.aStart
.Tab();
278 nEndTab
= rRange
.aEnd
.Tab();
281 for (SCTAB nTab
= nStartTab
; nTab
<= nEndTab
; nTab
++)
283 if ( !pTabMark
|| pTabMark
->GetTableSelect(nTab
) )
285 Rectangle aMMRect
= GetMMRect( rRange
.aStart
.Col(), rRange
.aStart
.Row(),
286 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), nTab
);
288 SdrPage
* pPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
289 OSL_ENSURE(pPage
,"Page ?");
292 SdrObjListIter
aIter( *pPage
, IM_FLAT
);
293 SdrObject
* pObject
= aIter
.Next();
296 if ( pObject
->GetObjIdentifier() == OBJ_OLE2
&&
297 aMMRect
.IsInside( pObject
->GetCurrentBoundRect() ) )
300 pObject
= aIter
.Next();
310 void ScDocument::StartAnimations( SCTAB nTab
, Window
* pWin
)
314 SdrPage
* pPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
315 OSL_ENSURE(pPage
,"Page ?");
319 SdrObjListIter
aIter( *pPage
, IM_FLAT
);
320 SdrObject
* pObject
= aIter
.Next();
323 if (pObject
->ISA(SdrGrafObj
))
325 SdrGrafObj
* pGrafObj
= (SdrGrafObj
*)pObject
;
326 if ( pGrafObj
->IsAnimated() )
328 const Rectangle
& rRect
= pGrafObj
->GetCurrentBoundRect();
329 pGrafObj
->StartAnimation( pWin
, rRect
.TopLeft(), rRect
.GetSize() );
332 pObject
= aIter
.Next();
337 bool ScDocument::HasBackgroundDraw( SCTAB nTab
, const Rectangle
& rMMRect
) const
339 // Gibt es Objekte auf dem Hintergrund-Layer, die (teilweise) von rMMRect
341 // (fuer Drawing-Optimierung, vor dem Hintergrund braucht dann nicht geloescht
346 SdrPage
* pPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
347 OSL_ENSURE(pPage
,"Page ?");
353 SdrObjListIter
aIter( *pPage
, IM_FLAT
);
354 SdrObject
* pObject
= aIter
.Next();
355 while (pObject
&& !bFound
)
357 if ( pObject
->GetLayer() == SC_LAYER_BACK
&& pObject
->GetCurrentBoundRect().IsOver( rMMRect
) )
359 pObject
= aIter
.Next();
365 bool ScDocument::HasAnyDraw( SCTAB nTab
, const Rectangle
& rMMRect
) const
367 // Gibt es ueberhaupt Objekte, die (teilweise) von rMMRect
369 // (um leere Seiten beim Drucken zu erkennen)
373 SdrPage
* pPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
374 OSL_ENSURE(pPage
,"Page ?");
380 SdrObjListIter
aIter( *pPage
, IM_FLAT
);
381 SdrObject
* pObject
= aIter
.Next();
382 while (pObject
&& !bFound
)
384 if ( pObject
->GetCurrentBoundRect().IsOver( rMMRect
) )
386 pObject
= aIter
.Next();
392 void ScDocument::EnsureGraphicNames()
395 pDrawLayer
->EnsureGraphicNames();
398 SdrObject
* ScDocument::GetObjectAtPoint( SCTAB nTab
, const Point
& rPos
)
400 // fuer Drag&Drop auf Zeichenobjekt
402 SdrObject
* pFound
= NULL
;
403 if (pDrawLayer
&& nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
405 SdrPage
* pPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
406 OSL_ENSURE(pPage
,"Page ?");
409 SdrObjListIter
aIter( *pPage
, IM_FLAT
);
410 SdrObject
* pObject
= aIter
.Next();
413 if ( pObject
->GetCurrentBoundRect().IsInside(rPos
) )
415 // Intern interessiert gar nicht
416 // Objekt vom Back-Layer nur, wenn kein Objekt von anderem Layer getroffen
418 SdrLayerID nLayer
= pObject
->GetLayer();
419 if ( (nLayer
!= SC_LAYER_INTERN
) && (nLayer
!= SC_LAYER_HIDDEN
) )
421 if ( nLayer
!= SC_LAYER_BACK
||
422 !pFound
|| pFound
->GetLayer() == SC_LAYER_BACK
)
428 // weitersuchen -> letztes (oberstes) getroffenes Objekt nehmen
430 pObject
= aIter
.Next();
437 bool ScDocument::IsPrintEmpty( SCTAB nTab
, SCCOL nStartCol
, SCROW nStartRow
,
438 SCCOL nEndCol
, SCROW nEndRow
, bool bLeftIsEmpty
,
439 ScRange
* pLastRange
, Rectangle
* pLastMM
) const
441 if (!IsBlockEmpty( nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
))
444 if (HasAttrib(ScRange(nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
), HASATTR_LINES
))
445 // We want to print sheets with borders even if there is no cell content.
449 if ( pLastRange
&& pLastMM
&& nTab
== pLastRange
->aStart
.Tab() &&
450 nStartRow
== pLastRange
->aStart
.Row() && nEndRow
== pLastRange
->aEnd
.Row() )
452 // keep vertical part of aMMRect, only update horizontal position
457 for (i
=0; i
<nStartCol
; i
++)
458 nLeft
+= GetColWidth(i
,nTab
);
460 for (i
=nStartCol
; i
<=nEndCol
; i
++)
461 nRight
+= GetColWidth(i
,nTab
);
463 aMMRect
.Left() = (long)(nLeft
* HMM_PER_TWIPS
);
464 aMMRect
.Right() = (long)(nRight
* HMM_PER_TWIPS
);
467 aMMRect
= GetMMRect( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
);
469 if ( pLastRange
&& pLastMM
)
471 *pLastRange
= ScRange( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
);
475 if ( HasAnyDraw( nTab
, aMMRect
))
478 if ( nStartCol
> 0 && !bLeftIsEmpty
)
480 // aehnlich wie in ScPrintFunc::AdjustPrintArea
481 //! ExtendPrintArea erst ab Start-Spalte des Druckbereichs
483 SCCOL nExtendCol
= nStartCol
- 1;
484 SCROW nTmpRow
= nEndRow
;
486 // ExtendMerge() is non-const, but called without refresh. GetPrinter()
487 // might create and assign a printer.
488 ScDocument
* pThis
= const_cast<ScDocument
*>(this);
490 pThis
->ExtendMerge( 0,nStartRow
, nExtendCol
,nTmpRow
, nTab
,
491 false ); // kein Refresh, incl. Attrs
493 OutputDevice
* pDev
= pThis
->GetPrinter();
494 pDev
->SetMapMode( MAP_PIXEL
); // wichtig fuer GetNeededSize
495 ExtendPrintArea( pDev
, nTab
, 0, nStartRow
, nExtendCol
, nEndRow
);
496 if ( nExtendCol
>= nStartCol
)
503 void ScDocument::Clear( bool bFromDestructor
)
505 TableContainer::iterator it
= maTabs
.begin();
506 for (;it
!= maTabs
.end(); ++it
)
509 delete pSelectionAttr
;
510 pSelectionAttr
= NULL
;
514 pDrawLayer
->ClearModel( bFromDestructor
);
518 bool ScDocument::HasDetectiveObjects(SCTAB nTab
) const
520 // looks for detective objects, annotations don't count
521 // (used to adjust scale so detective objects hit their cells better)
527 SdrPage
* pPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
528 OSL_ENSURE(pPage
,"Page ?");
531 SdrObjListIter
aIter( *pPage
, IM_DEEPNOGROUPS
);
532 SdrObject
* pObject
= aIter
.Next();
533 while (pObject
&& !bFound
)
535 // anything on the internal layer except captions (annotations)
536 if ( (pObject
->GetLayer() == SC_LAYER_INTERN
) && !ScDrawLayer::IsNoteCaption( pObject
) )
539 pObject
= aIter
.Next();
547 void ScDocument::UpdateFontCharSet()
549 // In alten Versionen (bis incl. 4.0 ohne SP) wurden beim Austausch zwischen
550 // Systemen die CharSets in den Font-Attributen nicht angepasst.
551 // Das muss fuer Dokumente bis incl SP2 nun nachgeholt werden:
552 // Alles, was nicht SYMBOL ist, wird auf den System-CharSet umgesetzt.
553 // Bei neuen Dokumenten (Version SC_FONTCHARSET) sollte der CharSet stimmen.
555 bool bUpdateOld
= ( nSrcVer
< SC_FONTCHARSET
);
557 rtl_TextEncoding eSysSet
= osl_getThreadTextEncoding();
558 if ( eSrcSet
!= eSysSet
|| bUpdateOld
)
563 ScDocumentPool
* pPool
= xPoolHelper
->GetDocPool();
564 nCount
= pPool
->GetItemCount2(ATTR_FONT
);
565 for (i
=0; i
<nCount
; i
++)
567 pItem
= (SvxFontItem
*)pPool
->GetItem2(ATTR_FONT
, i
);
568 if ( pItem
&& ( pItem
->GetCharSet() == eSrcSet
||
569 ( bUpdateOld
&& pItem
->GetCharSet() != RTL_TEXTENCODING_SYMBOL
) ) )
570 pItem
->SetCharSet(eSysSet
);
575 SfxItemPool
& rDrawPool
= pDrawLayer
->GetItemPool();
576 nCount
= rDrawPool
.GetItemCount2(EE_CHAR_FONTINFO
);
577 for (i
=0; i
<nCount
; i
++)
579 pItem
= (SvxFontItem
*)rDrawPool
.GetItem2(EE_CHAR_FONTINFO
, i
);
580 if ( pItem
&& ( pItem
->GetCharSet() == eSrcSet
||
581 ( bUpdateOld
&& pItem
->GetCharSet() != RTL_TEXTENCODING_SYMBOL
) ) )
582 pItem
->SetCharSet( eSysSet
);
588 void ScDocument::SetLoadingMedium( bool bVal
)
590 bLoadingMedium
= bVal
;
591 TableContainer::iterator it
= maTabs
.begin();
592 for (; it
!= maTabs
.end(); ++it
)
597 (*it
)->SetLoadingMedium(bVal
);
601 void ScDocument::SetImportingXML( bool bVal
)
603 bImportingXML
= bVal
;
605 pDrawLayer
->EnableAdjust(!bImportingXML
);
609 // #i57869# after loading, do the real RTL mirroring for the sheets that have the LoadingRTL flag set
611 for ( SCTAB nTab
=0; nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
]; nTab
++ )
612 if ( maTabs
[nTab
]->IsLoadingRTL() )
614 maTabs
[nTab
]->SetLoadingRTL( false );
615 SetLayoutRTL( nTab
, true ); // includes mirroring; bImportingXML must be cleared first
619 SetLoadingMedium(bVal
);
622 void ScDocument::SetXMLFromWrapper( bool bVal
)
624 bXMLFromWrapper
= bVal
;
627 rtl::Reference
<SvxForbiddenCharactersTable
> ScDocument::GetForbiddenCharacters()
629 return xForbiddenCharacters
;
632 void ScDocument::SetForbiddenCharacters( const rtl::Reference
<SvxForbiddenCharactersTable
> xNew
)
634 xForbiddenCharacters
= xNew
;
636 pEditEngine
->SetForbiddenCharsTable( xForbiddenCharacters
);
638 pDrawLayer
->SetForbiddenCharsTable( xForbiddenCharacters
);
641 bool ScDocument::IsValidAsianCompression() const
643 return ( nAsianCompression
!= SC_ASIANCOMPRESSION_INVALID
);
646 sal_uInt8
ScDocument::GetAsianCompression() const
648 if ( nAsianCompression
== SC_ASIANCOMPRESSION_INVALID
)
651 return nAsianCompression
;
654 void ScDocument::SetAsianCompression(sal_uInt8 nNew
)
656 nAsianCompression
= nNew
;
658 pEditEngine
->SetAsianCompressionMode( nAsianCompression
);
660 pDrawLayer
->SetCharCompressType( nAsianCompression
);
663 bool ScDocument::IsValidAsianKerning() const
665 return ( nAsianKerning
!= SC_ASIANKERNING_INVALID
);
668 bool ScDocument::GetAsianKerning() const
670 if ( nAsianKerning
== SC_ASIANKERNING_INVALID
)
673 return static_cast<bool>(nAsianKerning
);
676 void ScDocument::SetAsianKerning(bool bNew
)
678 nAsianKerning
= (sal_uInt8
)bNew
;
680 pEditEngine
->SetKernAsianPunctuation( static_cast<bool>( nAsianKerning
) );
682 pDrawLayer
->SetKernAsianPunctuation( static_cast<bool>( nAsianKerning
) );
685 void ScDocument::ApplyAsianEditSettings( ScEditEngineDefaulter
& rEngine
)
687 rEngine
.SetForbiddenCharsTable( xForbiddenCharacters
);
688 rEngine
.SetAsianCompressionMode( GetAsianCompression() );
689 rEngine
.SetKernAsianPunctuation( GetAsianKerning() );
692 void ScDocument::RebuildFormulaGroups()
695 for (nTab
=0; nTab
< static_cast<SCTAB
>(maTabs
.size()); nTab
++)
697 maTabs
[nTab
]->RebuildFormulaGroups();
700 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */