use insert function instead of for loop
[LibreOffice.git] / sc / source / filter / excel / xlroot.cxx
blob4ee2b155c8d76748a4a2d0d4d9d372283a588532
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 <utility>
22 #include <xlroot.hxx>
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>
50 #include <docuno.hxx>
51 #include <docsh.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>
64 #include <root.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 ================================================================
80 #ifdef DBG_UTIL
81 XclDebugObjCounter::~XclDebugObjCounter()
83 OSL_ENSURE( mnObjCnt == 0, "XclDebugObjCounter::~XclDebugObjCounter - wrong root object count" );
85 #endif
87 XclRootData::XclRootData( XclBiff eBiff, SfxMedium& rMedium,
88 rtl::Reference<SotStorage> xRootStrg, ScDocument& rDoc, rtl_TextEncoding eTextEnc, bool bExport ) :
89 meBiff( eBiff ),
90 meOutput( EXC_OUTPUT_BINARY ),
91 mrMedium( rMedium ),
92 mxRootStrg(std::move( xRootStrg )),
93 mrDoc( rDoc ),
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 ),
107 mnCharWidth( 110 ),
108 mnSpaceWidth(45),
109 mnScTab( 0 ),
110 mbExport( bExport )
112 if (!comphelper::IsFuzzing())
113 maUserName = SvtUserOptions().GetLastName();
114 if (maUserName.isEmpty())
115 maUserName = "Calc";
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
126 switch( meBiff )
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 );
147 else
148 mxExtDocOpt = std::make_shared<ScExtDocOptions>();
150 // screen pixel size
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 ) :
171 mrData( rRootData )
173 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
174 ++mrData.mnObjCnt;
175 #endif
177 // filter tracer
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
185 ++mrData.mnObjCnt;
186 #endif
189 XclRoot::~XclRoot()
191 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
192 --mrData.mnObjCnt;
193 #endif
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" );
201 return *this;
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 )
347 fValue -= 1.0;
348 return fValue;
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);
361 return aDateTime;
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: */