Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / excel / xlroot.cxx
blobf52a4ab3fa3f7988e13e774d50ebf50dc283c816
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <memory>
21 #include <xlroot.hxx>
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>
45 #include <docuno.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>
58 #include <root.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 ================================================================
74 #ifdef DBG_UTIL
75 XclDebugObjCounter::~XclDebugObjCounter()
77 OSL_ENSURE( mnObjCnt == 0, "XclDebugObjCounter::~XclDebugObjCounter - wrong root object count" );
79 #endif
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 ) :
85 meBiff( eBiff ),
86 meOutput( EXC_OUTPUT_BINARY ),
87 mrMedium( rMedium ),
88 mxRootStrg( xRootStrg ),
89 mrDoc( rDoc ),
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 ),
103 mnCharWidth( 110 ),
104 mnScTab( 0 ),
105 mbExport( bExport )
107 if (!utl::ConfigManager::IsFuzzing())
108 maUserName = SvtUserOptions().GetLastName();
109 if (maUserName.isEmpty())
110 maUserName = "Calc";
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
121 switch( meBiff )
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 ) );
143 else
144 mxExtDocOpt.reset( new ScExtDocOptions );
146 // screen pixel size
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 ) :
167 mrData( rRootData )
169 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
170 ++mrData.mnObjCnt;
171 #endif
173 // filter tracer
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
181 ++mrData.mnObjCnt;
182 #endif
185 XclRoot::~XclRoot()
187 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
188 --mrData.mnObjCnt;
189 #endif
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" );
197 return *this;
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
279 return mrData.mrDoc;
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 )
340 fValue -= 1.0;
341 return fValue;
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);
354 return aDateTime;
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: */