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 .
23 #include <sal/log.hxx>
24 #include <com/sun/star/awt/XDevice.hpp>
25 #include <com/sun/star/frame/Desktop.hpp>
26 #include <com/sun/star/frame/XFrame.hpp>
27 #include <com/sun/star/i18n/ScriptType.hpp>
28 #include <comphelper/lok.hxx>
29 #include <comphelper/processfactory.hxx>
30 #include <comphelper/servicehelper.hxx>
31 #include <sot/storage.hxx>
32 #include <vcl/svapp.hxx>
33 #include <svl/numformat.hxx>
34 #include <svl/stritem.hxx>
35 #include <svl/languageoptions.hxx>
36 #include <sfx2/objsh.hxx>
37 #include <sfx2/docfile.hxx>
38 #include <sfx2/sfxsids.hrc>
39 #include <vcl/font.hxx>
40 #include <vcl/settings.hxx>
41 #include <vcl/virdev.hxx>
42 #include <comphelper/diagnose_ex.hxx>
44 #include <editeng/editstat.hxx>
45 #include <scitems.hxx>
46 #include <editeng/eeitem.hxx>
47 #include <editeng/fhgtitem.hxx>
48 #include <document.hxx>
49 #include <docpool.hxx>
52 #include <editutil.hxx>
53 #include <drwlayer.hxx>
54 #include <scextopt.hxx>
55 #include <patattr.hxx>
56 #include <fapihelper.hxx>
57 #include <xlconst.hxx>
58 #include <xlstyle.hxx>
59 #include <xlchart.hxx>
60 #include <xltracer.hxx>
61 #include <xltools.hxx>
62 #include <comphelper/configuration.hxx>
63 #include <unotools/useroptions.hxx>
66 namespace ApiScriptType
= ::com::sun::star::i18n::ScriptType
;
68 using ::com::sun::star::uno::Exception
;
69 using ::com::sun::star::uno::Reference
;
70 using ::com::sun::star::uno::UNO_QUERY_THROW
;
71 using ::com::sun::star::uno::UNO_SET_THROW
;
72 using ::com::sun::star::awt::XDevice
;
73 using ::com::sun::star::awt::DeviceInfo
;
74 using ::com::sun::star::frame::XFrame
;
76 using namespace ::com::sun::star
;
78 // Global data ================================================================
81 XclDebugObjCounter::~XclDebugObjCounter()
83 OSL_ENSURE( mnObjCnt
== 0, "XclDebugObjCounter::~XclDebugObjCounter - wrong root object count" );
87 XclRootData::XclRootData( XclBiff eBiff
, SfxMedium
& rMedium
,
88 rtl::Reference
<SotStorage
> xRootStrg
, ScDocument
& rDoc
, rtl_TextEncoding eTextEnc
, bool bExport
) :
90 meOutput( EXC_OUTPUT_BINARY
),
92 mxRootStrg(std::move( xRootStrg
)),
94 meTextEnc( eTextEnc
),
95 meSysLang( Application::GetSettings().GetLanguageTag().getLanguageType() ),
96 meDocLang( Application::GetSettings().GetLanguageTag().getLanguageType() ),
97 meUILang( Application::GetSettings().GetUILanguageTag().getLanguageType() ),
98 mnDefApiScript( ApiScriptType::LATIN
),
99 maScMaxPos( mrDoc
.MaxCol(), mrDoc
.MaxRow(), MAXTAB
),
100 maXclMaxPos( EXC_MAXCOL2
, EXC_MAXROW2
, EXC_MAXTAB2
),
101 maMaxPos( EXC_MAXCOL2
, EXC_MAXROW2
, EXC_MAXTAB2
),
102 mxFontPropSetHlp( std::make_shared
<XclFontPropSetHelper
>() ),
103 mxChPropSetHlp( std::make_shared
<XclChPropSetHelper
>() ),
104 mxRD( std::make_shared
<RootData
>() ),
105 mfScreenPixelX( 50.0 ),
106 mfScreenPixelY( 50.0 ),
112 if (!comphelper::IsFuzzing())
113 maUserName
= SvtUserOptions().GetLastName();
114 if (maUserName
.isEmpty())
117 switch( ScGlobal::GetDefaultScriptType() )
119 case SvtScriptType::LATIN
: mnDefApiScript
= ApiScriptType::LATIN
; break;
120 case SvtScriptType::ASIAN
: mnDefApiScript
= ApiScriptType::ASIAN
; break;
121 case SvtScriptType::COMPLEX
: mnDefApiScript
= ApiScriptType::COMPLEX
; break;
122 default: SAL_WARN( "sc", "XclRootData::XclRootData - unknown script type" );
125 // maximum cell position
128 case EXC_BIFF2
: maXclMaxPos
.Set( EXC_MAXCOL2
, EXC_MAXROW2
, EXC_MAXTAB2
); break;
129 case EXC_BIFF3
: maXclMaxPos
.Set( EXC_MAXCOL3
, EXC_MAXROW3
, EXC_MAXTAB3
); break;
130 case EXC_BIFF4
: maXclMaxPos
.Set( EXC_MAXCOL4
, EXC_MAXROW4
, EXC_MAXTAB4
); break;
131 case EXC_BIFF5
: maXclMaxPos
.Set( EXC_MAXCOL5
, EXC_MAXROW5
, EXC_MAXTAB5
); break;
132 case EXC_BIFF8
: maXclMaxPos
.Set( EXC_MAXCOL8
, EXC_MAXROW8
, EXC_MAXTAB8
); break;
133 default: DBG_ERROR_BIFF();
135 maMaxPos
.SetCol( ::std::min( maScMaxPos
.Col(), maXclMaxPos
.Col() ) );
136 maMaxPos
.SetRow( ::std::min( maScMaxPos
.Row(), maXclMaxPos
.Row() ) );
137 maMaxPos
.SetTab( ::std::min( maScMaxPos
.Tab(), maXclMaxPos
.Tab() ) );
139 // document URL and path
140 if( const SfxStringItem
* pItem
= mrMedium
.GetItemSet().GetItem( SID_FILE_NAME
) )
141 maDocUrl
= pItem
->GetValue();
142 maBasePath
= maDocUrl
.copy( 0, maDocUrl
.lastIndexOf( '/' ) + 1 );
144 // extended document options - always own object, try to copy existing data from document
145 if( const ScExtDocOptions
* pOldDocOpt
= mrDoc
.GetExtDocOptions() )
146 mxExtDocOpt
= std::make_shared
<ScExtDocOptions
>( *pOldDocOpt
);
148 mxExtDocOpt
= std::make_shared
<ScExtDocOptions
>();
153 Reference
< frame::XDesktop2
> xFramesSupp
= frame::Desktop::create( ::comphelper::getProcessComponentContext() );
154 Reference
< XFrame
> xFrame( xFramesSupp
->getActiveFrame(), UNO_SET_THROW
);
155 Reference
< XDevice
> xDevice( xFrame
->getContainerWindow(), UNO_QUERY_THROW
);
156 DeviceInfo aDeviceInfo
= xDevice
->getInfo();
157 mfScreenPixelX
= (aDeviceInfo
.PixelPerMeterX
> 0) ? (100000.0 / aDeviceInfo
.PixelPerMeterX
) : 50.0;
158 mfScreenPixelY
= (aDeviceInfo
.PixelPerMeterY
> 0) ? (100000.0 / aDeviceInfo
.PixelPerMeterY
) : 50.0;
160 catch( const Exception
&)
162 TOOLS_WARN_EXCEPTION( "sc", "XclRootData::XclRootData - cannot get output device info");
166 XclRootData::~XclRootData()
170 XclRoot::XclRoot( XclRootData
& rRootData
) :
173 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
178 mrData
.mxTracer
= std::make_shared
<XclTracer
>( GetDocUrl() );
181 XclRoot::XclRoot( const XclRoot
& rRoot
) :
182 mrData( rRoot
.mrData
)
184 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
191 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
196 XclRoot
& XclRoot::operator=( const XclRoot
& rRoot
)
198 (void)rRoot
; // avoid compiler warning
199 // allowed for assignment in derived classes - but test if the same root data is used
200 OSL_ENSURE( &mrData
== &rRoot
.mrData
, "XclRoot::operator= - incompatible root data" );
204 void XclRoot::SetTextEncoding( rtl_TextEncoding eTextEnc
)
206 if( eTextEnc
!= RTL_TEXTENCODING_DONTKNOW
)
207 mrData
.meTextEnc
= eTextEnc
;
210 void XclRoot::SetCharWidth( const XclFontData
& rFontData
)
212 mrData
.mnCharWidth
= 0;
213 bool bIsLOK
= comphelper::LibreOfficeKit::isActive();
214 if( OutputDevice
* pPrinter
= GetPrinter( bIsLOK
) )
216 vcl::Font
aFont( rFontData
.maName
, Size( 0, rFontData
.mnHeight
) );
217 aFont
.SetFamily( rFontData
.GetScFamily( GetTextEncoding() ) );
218 aFont
.SetCharSet( rFontData
.GetFontEncoding() );
219 aFont
.SetWeight( rFontData
.GetScWeight() );
220 pPrinter
->SetFont( aFont
);
221 // Usually digits have the same width, but in some fonts they don't ...
222 // Match the import in sc/source/filter/oox/unitconverter.cxx
223 // UnitConverter::finalizeImport()
224 for (sal_Unicode cChar
= '0'; cChar
<= '9'; ++cChar
)
225 mrData
.mnCharWidth
= std::max( pPrinter
->GetTextWidth( OUString(cChar
)), mrData
.mnCharWidth
);
227 // Set the width of space ' ' character.
228 mrData
.mnSpaceWidth
= pPrinter
->GetTextWidth(OUString(' '));
230 if( mrData
.mnCharWidth
<= 0 )
232 // #i48717# Win98 with HP LaserJet returns 0
233 SAL_WARN( "sc", "XclRoot::SetCharWidth - invalid character width (no printer?)" );
234 mrData
.mnCharWidth
= 11 * rFontData
.mnHeight
/ 20;
236 if (mrData
.mnSpaceWidth
<= 0)
238 SAL_WARN( "sc", "XclRoot::SetCharWidth - invalid character width (no printer?)" );
239 mrData
.mnSpaceWidth
= 45;
243 sal_Int32
XclRoot::GetHmmFromPixelX( double fPixelX
) const
245 return static_cast< sal_Int32
>( fPixelX
* mrData
.mfScreenPixelX
+ 0.5 );
248 sal_Int32
XclRoot::GetHmmFromPixelY( double fPixelY
) const
250 return static_cast< sal_Int32
>( fPixelY
* mrData
.mfScreenPixelY
+ 0.5 );
253 uno::Sequence
< beans::NamedValue
> XclRoot::RequestEncryptionData( ::comphelper::IDocPasswordVerifier
& rVerifier
) const
255 ::std::vector
< OUString
> aDefaultPasswords
{ XclRootData::gaDefPassword
};
256 return ScfApiHelper::QueryEncryptionDataForMedium( mrData
.mrMedium
, rVerifier
, &aDefaultPasswords
);
259 bool XclRoot::HasVbaStorage() const
261 rtl::Reference
<SotStorage
> xRootStrg
= GetRootStorage();
262 return xRootStrg
.is() && xRootStrg
->IsContained( EXC_STORAGE_VBA_PROJECT
);
265 rtl::Reference
<SotStorage
> XclRoot::OpenStorage( rtl::Reference
<SotStorage
> const & xStrg
, const OUString
& rStrgName
) const
267 return mrData
.mbExport
?
268 ScfTools::OpenStorageWrite( xStrg
, rStrgName
) :
269 ScfTools::OpenStorageRead( xStrg
, rStrgName
);
272 rtl::Reference
<SotStorage
> XclRoot::OpenStorage(const OUString
& rStrgName
) const
274 return OpenStorage( GetRootStorage(), rStrgName
);
277 rtl::Reference
<SotStorageStream
> XclRoot::OpenStream( rtl::Reference
<SotStorage
> const & xStrg
, const OUString
& rStrmName
) const
279 return mrData
.mbExport
?
280 ScfTools::OpenStorageStreamWrite( xStrg
, rStrmName
) :
281 ScfTools::OpenStorageStreamRead( xStrg
, rStrmName
);
284 rtl::Reference
<SotStorageStream
> XclRoot::OpenStream(const OUString
& rStrmName
) const
286 return OpenStream( GetRootStorage(), rStrmName
);
289 ScDocShell
* XclRoot::GetDocShell() const
291 return GetDoc().GetDocumentShell();
294 ScModelObj
* XclRoot::GetDocModelObj() const
296 ScDocShell
* pDocShell
= GetDocShell();
297 return pDocShell
? pDocShell
->GetModel() : nullptr;
300 OutputDevice
* XclRoot::GetPrinter(bool bForceVirtDev
) const
302 return GetDoc().GetRefDevice(bForceVirtDev
);
305 ScStyleSheetPool
& XclRoot::GetStyleSheetPool() const
307 return *GetDoc().GetStyleSheetPool();
310 ScRangeName
& XclRoot::GetNamedRanges() const
312 return *GetDoc().GetRangeName();
315 SdrPage
* XclRoot::GetSdrPage( SCTAB nScTab
) const
317 return ((nScTab
>= 0) && GetDoc().GetDrawLayer()) ?
318 GetDoc().GetDrawLayer()->GetPage( static_cast< sal_uInt16
>( nScTab
) ) : nullptr;
321 SvNumberFormatter
& XclRoot::GetFormatter() const
323 return *GetDoc().GetFormatTable();
326 const Date
& XclRoot::GetNullDate() const
328 return GetFormatter().GetNullDate();
331 sal_uInt16
XclRoot::GetBaseYear() const
333 // return 1904 for 1904-01-01, and 1900 for 1899-12-30
334 return (GetNullDate().GetYear() == 1904) ? 1904 : 1900;
337 const DateTime
theOurCompatNullDate( Date( 30, 12, 1899 ));
338 const DateTime
theExcelCutOverDate( Date( 1, 3, 1900 ));
340 double XclRoot::GetDoubleFromDateTime( const DateTime
& rDateTime
) const
342 double fValue
= DateTime::Sub( rDateTime
, DateTime( GetNullDate()));
343 // adjust dates before 1900-03-01 to get correct time values in the range [0.0,1.0)
344 /* XXX: this is only used when reading BIFF, otherwise we'd have to check
345 * for dateCompatibility==true as mentioned below. */
346 if( rDateTime
< theExcelCutOverDate
&& GetNullDate() == theOurCompatNullDate
)
351 DateTime
XclRoot::GetDateTimeFromDouble( double fValue
) const
353 DateTime aDateTime
= DateTime( GetNullDate()) + fValue
;
354 // adjust dates before 1900-03-01 to get correct time values
355 /* FIXME: correction should only be done when writing BIFF or OOXML
356 * transitional with dateCompatibility==true (or absent for default true),
357 * but not if strict ISO/IEC 29500 which does not have the Excel error
358 * compatibility and the null date is the same 1899-12-30 as ours. */
359 if( aDateTime
< theExcelCutOverDate
&& GetNullDate() == theOurCompatNullDate
)
360 aDateTime
.AddDays(1);
364 ScEditEngineDefaulter
& XclRoot::GetEditEngine() const
366 if( !mrData
.mxEditEngine
)
368 mrData
.mxEditEngine
= std::make_shared
<ScEditEngineDefaulter
>( GetDoc().GetEnginePool() );
369 ScEditEngineDefaulter
& rEE
= *mrData
.mxEditEngine
;
370 rEE
.SetRefMapMode(MapMode(MapUnit::Map100thMM
));
371 rEE
.SetEditTextObjectPool( GetDoc().GetEditPool() );
372 rEE
.SetUpdateLayout( false );
373 rEE
.EnableUndo( false );
374 rEE
.SetControlWord( rEE
.GetControlWord() & ~EEControlBits::ALLOWBIGOBJS
);
376 return *mrData
.mxEditEngine
;
379 ScHeaderEditEngine
& XclRoot::GetHFEditEngine() const
381 if( !mrData
.mxHFEditEngine
)
383 mrData
.mxHFEditEngine
= std::make_shared
<ScHeaderEditEngine
>( EditEngine::CreatePool().get() );
384 ScHeaderEditEngine
& rEE
= *mrData
.mxHFEditEngine
;
385 rEE
.SetRefMapMode(MapMode(MapUnit::MapTwip
)); // headers/footers use twips as default metric
386 rEE
.SetUpdateLayout( false );
387 rEE
.EnableUndo( false );
388 rEE
.SetControlWord( rEE
.GetControlWord() & ~EEControlBits::ALLOWBIGOBJS
);
390 // set Calc header/footer defaults
391 auto pEditSet
= std::make_unique
<SfxItemSet
>( rEE
.GetEmptyItemSet() );
392 SfxItemSetFixed
<ATTR_PATTERN_START
, ATTR_PATTERN_END
> aItemSet( *GetDoc().GetPool() );
393 ScPatternAttr::FillToEditItemSet( *pEditSet
, aItemSet
);
394 // FillToEditItemSet() adjusts font height to 1/100th mm, we need twips
395 pEditSet
->Put( aItemSet
.Get( ATTR_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT
) );
396 pEditSet
->Put( aItemSet
.Get( ATTR_CJK_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK
) );
397 pEditSet
->Put( aItemSet
.Get( ATTR_CTL_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL
) );
398 rEE
.SetDefaults( std::move(pEditSet
) ); // takes ownership
400 return *mrData
.mxHFEditEngine
;
403 EditEngine
& XclRoot::GetDrawEditEngine() const
405 if( !mrData
.mxDrawEditEng
)
407 mrData
.mxDrawEditEng
= std::make_shared
<EditEngine
>( &GetDoc().GetDrawLayer()->GetItemPool() );
408 EditEngine
& rEE
= *mrData
.mxDrawEditEng
;
409 rEE
.SetStyleSheetPool(static_cast<SfxStyleSheetPool
*>(GetDoc().GetDrawLayer()->GetStyleSheetPool()));
410 rEE
.SetRefMapMode(MapMode(MapUnit::Map100thMM
));
411 rEE
.SetUpdateLayout( false );
412 rEE
.EnableUndo( false );
413 rEE
.SetControlWord( rEE
.GetControlWord() & ~EEControlBits::ALLOWBIGOBJS
);
415 return *mrData
.mxDrawEditEng
;
418 XclFontPropSetHelper
& XclRoot::GetFontPropSetHelper() const
420 return *mrData
.mxFontPropSetHlp
;
423 XclChPropSetHelper
& XclRoot::GetChartPropSetHelper() const
425 return *mrData
.mxChPropSetHlp
;
428 ScExtDocOptions
& XclRoot::GetExtDocOptions() const
430 return *mrData
.mxExtDocOpt
;
433 XclTracer
& XclRoot::GetTracer() const
435 return *mrData
.mxTracer
;
438 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */