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 .
22 #include <sal/log.hxx>
23 #include <com/sun/star/awt/XDevice.hpp>
24 #include <com/sun/star/frame/Desktop.hpp>
25 #include <com/sun/star/frame/XFrame.hpp>
26 #include <com/sun/star/i18n/ScriptType.hpp>
27 #include <comphelper/processfactory.hxx>
28 #include <comphelper/servicehelper.hxx>
29 #include <sot/storage.hxx>
30 #include <vcl/svapp.hxx>
31 #include <svl/stritem.hxx>
32 #include <svl/languageoptions.hxx>
33 #include <sfx2/objsh.hxx>
34 #include <sfx2/docfile.hxx>
35 #include <sfx2/sfxsids.hrc>
36 #include <vcl/font.hxx>
37 #include <vcl/settings.hxx>
38 #include <tools/diagnose_ex.h>
40 #include <editeng/editstat.hxx>
41 #include <scitems.hxx>
42 #include <editeng/eeitem.hxx>
43 #include <document.hxx>
44 #include <docpool.hxx>
46 #include <editutil.hxx>
47 #include <drwlayer.hxx>
48 #include <scextopt.hxx>
49 #include <patattr.hxx>
50 #include <fapihelper.hxx>
51 #include <xlconst.hxx>
52 #include <xlstyle.hxx>
53 #include <xlchart.hxx>
54 #include <xltracer.hxx>
55 #include <xltools.hxx>
56 #include <unotools/configmgr.hxx>
57 #include <unotools/useroptions.hxx>
60 namespace ApiScriptType
= ::com::sun::star::i18n::ScriptType
;
62 using ::com::sun::star::uno::Exception
;
63 using ::com::sun::star::uno::Reference
;
64 using ::com::sun::star::uno::UNO_QUERY_THROW
;
65 using ::com::sun::star::uno::UNO_SET_THROW
;
66 using ::com::sun::star::awt::XDevice
;
67 using ::com::sun::star::awt::DeviceInfo
;
68 using ::com::sun::star::frame::XFrame
;
70 using namespace ::com::sun::star
;
72 // Global data ================================================================
75 XclDebugObjCounter::~XclDebugObjCounter()
77 OSL_ENSURE( mnObjCnt
== 0, "XclDebugObjCounter::~XclDebugObjCounter - wrong root object count" );
81 const OUStringLiteral
XclRootData::gaDefPassword( "VelvetSweatshop" );
83 XclRootData::XclRootData( XclBiff eBiff
, SfxMedium
& rMedium
,
84 tools::SvRef
<SotStorage
> const & xRootStrg
, ScDocument
& rDoc
, rtl_TextEncoding eTextEnc
, bool bExport
) :
86 meOutput( EXC_OUTPUT_BINARY
),
88 mxRootStrg( xRootStrg
),
90 meTextEnc( eTextEnc
),
91 meSysLang( Application::GetSettings().GetLanguageTag().getLanguageType() ),
92 meDocLang( Application::GetSettings().GetLanguageTag().getLanguageType() ),
93 meUILang( Application::GetSettings().GetUILanguageTag().getLanguageType() ),
94 mnDefApiScript( ApiScriptType::LATIN
),
95 maScMaxPos( mrDoc
.MaxCol(), mrDoc
.MaxRow(), MAXTAB
),
96 maXclMaxPos( EXC_MAXCOL2
, EXC_MAXROW2
, EXC_MAXTAB2
),
97 maMaxPos( EXC_MAXCOL2
, EXC_MAXROW2
, EXC_MAXTAB2
),
98 mxFontPropSetHlp( new XclFontPropSetHelper
),
99 mxChPropSetHlp( new XclChPropSetHelper
),
100 mxRD( new RootData
),
101 mfScreenPixelX( 50.0 ),
102 mfScreenPixelY( 50.0 ),
107 if (!utl::ConfigManager::IsFuzzing())
108 maUserName
= SvtUserOptions().GetLastName();
109 if (maUserName
.isEmpty())
112 switch( ScGlobal::GetDefaultScriptType() )
114 case SvtScriptType::LATIN
: mnDefApiScript
= ApiScriptType::LATIN
; break;
115 case SvtScriptType::ASIAN
: mnDefApiScript
= ApiScriptType::ASIAN
; break;
116 case SvtScriptType::COMPLEX
: mnDefApiScript
= ApiScriptType::COMPLEX
; break;
117 default: SAL_WARN( "sc", "XclRootData::XclRootData - unknown script type" );
120 // maximum cell position
123 case EXC_BIFF2
: maXclMaxPos
.Set( EXC_MAXCOL2
, EXC_MAXROW2
, EXC_MAXTAB2
); break;
124 case EXC_BIFF3
: maXclMaxPos
.Set( EXC_MAXCOL3
, EXC_MAXROW3
, EXC_MAXTAB3
); break;
125 case EXC_BIFF4
: maXclMaxPos
.Set( EXC_MAXCOL4
, EXC_MAXROW4
, EXC_MAXTAB4
); break;
126 case EXC_BIFF5
: maXclMaxPos
.Set( EXC_MAXCOL5
, EXC_MAXROW5
, EXC_MAXTAB5
); break;
127 case EXC_BIFF8
: maXclMaxPos
.Set( EXC_MAXCOL8
, EXC_MAXROW8
, EXC_MAXTAB8
); break;
128 default: DBG_ERROR_BIFF();
130 maMaxPos
.SetCol( ::std::min( maScMaxPos
.Col(), maXclMaxPos
.Col() ) );
131 maMaxPos
.SetRow( ::std::min( maScMaxPos
.Row(), maXclMaxPos
.Row() ) );
132 maMaxPos
.SetTab( ::std::min( maScMaxPos
.Tab(), maXclMaxPos
.Tab() ) );
134 // document URL and path
135 if( const SfxItemSet
* pItemSet
= mrMedium
.GetItemSet() )
136 if( const SfxStringItem
* pItem
= pItemSet
->GetItem
<SfxStringItem
>( SID_FILE_NAME
) )
137 maDocUrl
= pItem
->GetValue();
138 maBasePath
= maDocUrl
.copy( 0, maDocUrl
.lastIndexOf( '/' ) + 1 );
140 // extended document options - always own object, try to copy existing data from document
141 if( const ScExtDocOptions
* pOldDocOpt
= mrDoc
.GetExtDocOptions() )
142 mxExtDocOpt
.reset( new ScExtDocOptions( *pOldDocOpt
) );
144 mxExtDocOpt
.reset( new ScExtDocOptions
);
149 Reference
< frame::XDesktop2
> xFramesSupp
= frame::Desktop::create( ::comphelper::getProcessComponentContext() );
150 Reference
< XFrame
> xFrame( xFramesSupp
->getActiveFrame(), UNO_SET_THROW
);
151 Reference
< XDevice
> xDevice( xFrame
->getContainerWindow(), UNO_QUERY_THROW
);
152 DeviceInfo aDeviceInfo
= xDevice
->getInfo();
153 mfScreenPixelX
= (aDeviceInfo
.PixelPerMeterX
> 0) ? (100000.0 / aDeviceInfo
.PixelPerMeterX
) : 50.0;
154 mfScreenPixelY
= (aDeviceInfo
.PixelPerMeterY
> 0) ? (100000.0 / aDeviceInfo
.PixelPerMeterY
) : 50.0;
156 catch( const Exception
&)
158 TOOLS_WARN_EXCEPTION( "sc", "XclRootData::XclRootData - cannot get output device info");
162 XclRootData::~XclRootData()
166 XclRoot::XclRoot( XclRootData
& rRootData
) :
169 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
174 mrData
.mxTracer
.reset( new XclTracer( GetDocUrl() ) );
177 XclRoot::XclRoot( const XclRoot
& rRoot
) :
178 mrData( rRoot
.mrData
)
180 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
187 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
192 XclRoot
& XclRoot::operator=( const XclRoot
& rRoot
)
194 (void)rRoot
; // avoid compiler warning
195 // allowed for assignment in derived classes - but test if the same root data is used
196 OSL_ENSURE( &mrData
== &rRoot
.mrData
, "XclRoot::operator= - incompatible root data" );
200 void XclRoot::SetTextEncoding( rtl_TextEncoding eTextEnc
)
202 if( eTextEnc
!= RTL_TEXTENCODING_DONTKNOW
)
203 mrData
.meTextEnc
= eTextEnc
;
206 void XclRoot::SetCharWidth( const XclFontData
& rFontData
)
208 mrData
.mnCharWidth
= 0;
209 if( OutputDevice
* pPrinter
= GetPrinter() )
211 vcl::Font
aFont( rFontData
.maName
, Size( 0, rFontData
.mnHeight
) );
212 aFont
.SetFamily( rFontData
.GetScFamily( GetTextEncoding() ) );
213 aFont
.SetCharSet( rFontData
.GetFontEncoding() );
214 aFont
.SetWeight( rFontData
.GetScWeight() );
215 pPrinter
->SetFont( aFont
);
216 // Usually digits have the same width, but in some fonts they don't ...
217 // Match the import in sc/source/filter/oox/unitconverter.cxx
218 // UnitConverter::finalizeImport()
219 for (sal_Unicode cChar
= '0'; cChar
<= '9'; ++cChar
)
220 mrData
.mnCharWidth
= std::max( pPrinter
->GetTextWidth( OUString(cChar
)), mrData
.mnCharWidth
);
222 if( mrData
.mnCharWidth
<= 0 )
224 // #i48717# Win98 with HP LaserJet returns 0
225 SAL_WARN( "sc", "XclRoot::SetCharWidth - invalid character width (no printer?)" );
226 mrData
.mnCharWidth
= 11 * rFontData
.mnHeight
/ 20;
230 sal_Int32
XclRoot::GetHmmFromPixelX( double fPixelX
) const
232 return static_cast< sal_Int32
>( fPixelX
* mrData
.mfScreenPixelX
+ 0.5 );
235 sal_Int32
XclRoot::GetHmmFromPixelY( double fPixelY
) const
237 return static_cast< sal_Int32
>( fPixelY
* mrData
.mfScreenPixelY
+ 0.5 );
240 uno::Sequence
< beans::NamedValue
> XclRoot::RequestEncryptionData( ::comphelper::IDocPasswordVerifier
& rVerifier
) const
242 ::std::vector
< OUString
> aDefaultPasswords
;
243 aDefaultPasswords
.push_back( XclRootData::gaDefPassword
);
244 return ScfApiHelper::QueryEncryptionDataForMedium( mrData
.mrMedium
, rVerifier
, &aDefaultPasswords
);
247 bool XclRoot::HasVbaStorage() const
249 tools::SvRef
<SotStorage
> xRootStrg
= GetRootStorage();
250 return xRootStrg
.is() && xRootStrg
->IsContained( EXC_STORAGE_VBA_PROJECT
);
253 tools::SvRef
<SotStorage
> XclRoot::OpenStorage( tools::SvRef
<SotStorage
> const & xStrg
, const OUString
& rStrgName
) const
255 return mrData
.mbExport
?
256 ScfTools::OpenStorageWrite( xStrg
, rStrgName
) :
257 ScfTools::OpenStorageRead( xStrg
, rStrgName
);
260 tools::SvRef
<SotStorage
> XclRoot::OpenStorage( const OUString
& rStrgName
) const
262 return OpenStorage( GetRootStorage(), rStrgName
);
265 tools::SvRef
<SotStorageStream
> XclRoot::OpenStream( tools::SvRef
<SotStorage
> const & xStrg
, const OUString
& rStrmName
) const
267 return mrData
.mbExport
?
268 ScfTools::OpenStorageStreamWrite( xStrg
, rStrmName
) :
269 ScfTools::OpenStorageStreamRead( xStrg
, rStrmName
);
272 tools::SvRef
<SotStorageStream
> XclRoot::OpenStream( const OUString
& rStrmName
) const
274 return OpenStream( GetRootStorage(), rStrmName
);
277 ScDocument
& XclRoot::GetDoc() const
282 SfxObjectShell
* XclRoot::GetDocShell() const
284 return GetDoc().GetDocumentShell();
287 ScModelObj
* XclRoot::GetDocModelObj() const
289 SfxObjectShell
* pDocShell
= GetDocShell();
290 return pDocShell
? comphelper::getUnoTunnelImplementation
<ScModelObj
>( pDocShell
->GetModel() ) : nullptr;
293 OutputDevice
* XclRoot::GetPrinter() const
295 return GetDoc().GetRefDevice();
298 ScStyleSheetPool
& XclRoot::GetStyleSheetPool() const
300 return *GetDoc().GetStyleSheetPool();
303 ScRangeName
& XclRoot::GetNamedRanges() const
305 return *GetDoc().GetRangeName();
308 SdrPage
* XclRoot::GetSdrPage( SCTAB nScTab
) const
310 return ((nScTab
>= 0) && GetDoc().GetDrawLayer()) ?
311 GetDoc().GetDrawLayer()->GetPage( static_cast< sal_uInt16
>( nScTab
) ) : nullptr;
314 SvNumberFormatter
& XclRoot::GetFormatter() const
316 return *GetDoc().GetFormatTable();
319 DateTime
XclRoot::GetNullDate() const
321 return GetFormatter().GetNullDate();
324 sal_uInt16
XclRoot::GetBaseYear() const
326 // return 1904 for 1904-01-01, and 1900 for 1899-12-30
327 return (GetNullDate().GetYear() == 1904) ? 1904 : 1900;
330 static const DateTime
theOurCompatNullDate( Date( 30, 12, 1899 ));
331 static const DateTime
theExcelCutOverDate( Date( 1, 3, 1900 ));
333 double XclRoot::GetDoubleFromDateTime( const DateTime
& rDateTime
) const
335 double fValue
= rDateTime
- GetNullDate();
336 // adjust dates before 1900-03-01 to get correct time values in the range [0.0,1.0)
337 /* XXX: this is only used when reading BIFF, otherwise we'd have to check
338 * for dateCompatibility==true as mentioned below. */
339 if( rDateTime
< theExcelCutOverDate
&& GetNullDate() == theOurCompatNullDate
)
344 DateTime
XclRoot::GetDateTimeFromDouble( double fValue
) const
346 DateTime aDateTime
= GetNullDate() + fValue
;
347 // adjust dates before 1900-03-01 to get correct time values
348 /* FIXME: correction should only be done when writing BIFF or OOXML
349 * transitional with dateCompatibility==true (or absent for default true),
350 * but not if strict ISO/IEC 29500 which does not have the Excel error
351 * compatibility and the null date is the same 1899-12-30 as ours. */
352 if( aDateTime
< theExcelCutOverDate
&& GetNullDate() == theOurCompatNullDate
)
353 aDateTime
.AddDays(1);
357 ScEditEngineDefaulter
& XclRoot::GetEditEngine() const
359 if( !mrData
.mxEditEngine
.get() )
361 mrData
.mxEditEngine
.reset( new ScEditEngineDefaulter( GetDoc().GetEnginePool() ) );
362 ScEditEngineDefaulter
& rEE
= *mrData
.mxEditEngine
;
363 rEE
.SetRefMapMode(MapMode(MapUnit::Map100thMM
));
364 rEE
.SetEditTextObjectPool( GetDoc().GetEditPool() );
365 rEE
.SetUpdateMode( false );
366 rEE
.EnableUndo( false );
367 rEE
.SetControlWord( rEE
.GetControlWord() & ~EEControlBits::ALLOWBIGOBJS
);
369 return *mrData
.mxEditEngine
;
372 ScHeaderEditEngine
& XclRoot::GetHFEditEngine() const
374 if( !mrData
.mxHFEditEngine
.get() )
376 mrData
.mxHFEditEngine
.reset( new ScHeaderEditEngine( EditEngine::CreatePool() ) );
377 ScHeaderEditEngine
& rEE
= *mrData
.mxHFEditEngine
;
378 rEE
.SetRefMapMode(MapMode(MapUnit::MapTwip
)); // headers/footers use twips as default metric
379 rEE
.SetUpdateMode( false );
380 rEE
.EnableUndo( false );
381 rEE
.SetControlWord( rEE
.GetControlWord() & ~EEControlBits::ALLOWBIGOBJS
);
383 // set Calc header/footer defaults
384 auto pEditSet
= std::make_unique
<SfxItemSet
>( rEE
.GetEmptyItemSet() );
385 SfxItemSet
aItemSet( *GetDoc().GetPool(), svl::Items
<ATTR_PATTERN_START
, ATTR_PATTERN_END
>{} );
386 ScPatternAttr::FillToEditItemSet( *pEditSet
, aItemSet
);
387 // FillToEditItemSet() adjusts font height to 1/100th mm, we need twips
388 pEditSet
->Put( aItemSet
.Get( ATTR_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT
) );
389 pEditSet
->Put( aItemSet
.Get( ATTR_CJK_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK
) );
390 pEditSet
->Put( aItemSet
.Get( ATTR_CTL_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL
) );
391 rEE
.SetDefaults( std::move(pEditSet
) ); // takes ownership
393 return *mrData
.mxHFEditEngine
;
396 EditEngine
& XclRoot::GetDrawEditEngine() const
398 if( !mrData
.mxDrawEditEng
.get() )
400 mrData
.mxDrawEditEng
.reset( new EditEngine( &GetDoc().GetDrawLayer()->GetItemPool() ) );
401 EditEngine
& rEE
= *mrData
.mxDrawEditEng
;
402 rEE
.SetRefMapMode(MapMode(MapUnit::Map100thMM
));
403 rEE
.SetUpdateMode( false );
404 rEE
.EnableUndo( false );
405 rEE
.SetControlWord( rEE
.GetControlWord() & ~EEControlBits::ALLOWBIGOBJS
);
407 return *mrData
.mxDrawEditEng
;
410 XclFontPropSetHelper
& XclRoot::GetFontPropSetHelper() const
412 return *mrData
.mxFontPropSetHlp
;
415 XclChPropSetHelper
& XclRoot::GetChartPropSetHelper() const
417 return *mrData
.mxChPropSetHlp
;
420 ScExtDocOptions
& XclRoot::GetExtDocOptions() const
422 return *mrData
.mxExtDocOpt
;
425 XclTracer
& XclRoot::GetTracer() const
427 return *mrData
.mxTracer
;
430 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */