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/numformat.hxx>
32 #include <svl/stritem.hxx>
33 #include <svl/languageoptions.hxx>
34 #include <sfx2/objsh.hxx>
35 #include <sfx2/docfile.hxx>
36 #include <sfx2/sfxsids.hrc>
37 #include <vcl/font.hxx>
38 #include <vcl/settings.hxx>
39 #include <tools/diagnose_ex.h>
41 #include <editeng/editstat.hxx>
42 #include <scitems.hxx>
43 #include <editeng/eeitem.hxx>
44 #include <editeng/fhgtitem.hxx>
45 #include <document.hxx>
46 #include <docpool.hxx>
48 #include <editutil.hxx>
49 #include <drwlayer.hxx>
50 #include <scextopt.hxx>
51 #include <patattr.hxx>
52 #include <fapihelper.hxx>
53 #include <xlconst.hxx>
54 #include <xlstyle.hxx>
55 #include <xlchart.hxx>
56 #include <xltracer.hxx>
57 #include <xltools.hxx>
58 #include <unotools/configmgr.hxx>
59 #include <unotools/useroptions.hxx>
62 namespace ApiScriptType
= ::com::sun::star::i18n::ScriptType
;
64 using ::com::sun::star::uno::Exception
;
65 using ::com::sun::star::uno::Reference
;
66 using ::com::sun::star::uno::UNO_QUERY_THROW
;
67 using ::com::sun::star::uno::UNO_SET_THROW
;
68 using ::com::sun::star::awt::XDevice
;
69 using ::com::sun::star::awt::DeviceInfo
;
70 using ::com::sun::star::frame::XFrame
;
72 using namespace ::com::sun::star
;
74 // Global data ================================================================
77 XclDebugObjCounter::~XclDebugObjCounter()
79 OSL_ENSURE( mnObjCnt
== 0, "XclDebugObjCounter::~XclDebugObjCounter - wrong root object count" );
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( std::make_shared
<XclFontPropSetHelper
>() ),
99 mxChPropSetHlp( std::make_shared
<XclChPropSetHelper
>() ),
100 mxRD( std::make_shared
<RootData
>() ),
101 mfScreenPixelX( 50.0 ),
102 mfScreenPixelY( 50.0 ),
108 if (!utl::ConfigManager::IsFuzzing())
109 maUserName
= SvtUserOptions().GetLastName();
110 if (maUserName
.isEmpty())
113 switch( ScGlobal::GetDefaultScriptType() )
115 case SvtScriptType::LATIN
: mnDefApiScript
= ApiScriptType::LATIN
; break;
116 case SvtScriptType::ASIAN
: mnDefApiScript
= ApiScriptType::ASIAN
; break;
117 case SvtScriptType::COMPLEX
: mnDefApiScript
= ApiScriptType::COMPLEX
; break;
118 default: SAL_WARN( "sc", "XclRootData::XclRootData - unknown script type" );
121 // maximum cell position
124 case EXC_BIFF2
: maXclMaxPos
.Set( EXC_MAXCOL2
, EXC_MAXROW2
, EXC_MAXTAB2
); break;
125 case EXC_BIFF3
: maXclMaxPos
.Set( EXC_MAXCOL3
, EXC_MAXROW3
, EXC_MAXTAB3
); break;
126 case EXC_BIFF4
: maXclMaxPos
.Set( EXC_MAXCOL4
, EXC_MAXROW4
, EXC_MAXTAB4
); break;
127 case EXC_BIFF5
: maXclMaxPos
.Set( EXC_MAXCOL5
, EXC_MAXROW5
, EXC_MAXTAB5
); break;
128 case EXC_BIFF8
: maXclMaxPos
.Set( EXC_MAXCOL8
, EXC_MAXROW8
, EXC_MAXTAB8
); break;
129 default: DBG_ERROR_BIFF();
131 maMaxPos
.SetCol( ::std::min( maScMaxPos
.Col(), maXclMaxPos
.Col() ) );
132 maMaxPos
.SetRow( ::std::min( maScMaxPos
.Row(), maXclMaxPos
.Row() ) );
133 maMaxPos
.SetTab( ::std::min( maScMaxPos
.Tab(), maXclMaxPos
.Tab() ) );
135 // document URL and path
136 if( const SfxItemSet
* pItemSet
= mrMedium
.GetItemSet() )
137 if( const SfxStringItem
* pItem
= pItemSet
->GetItem
<SfxStringItem
>( SID_FILE_NAME
) )
138 maDocUrl
= pItem
->GetValue();
139 maBasePath
= maDocUrl
.copy( 0, maDocUrl
.lastIndexOf( '/' ) + 1 );
141 // extended document options - always own object, try to copy existing data from document
142 if( const ScExtDocOptions
* pOldDocOpt
= mrDoc
.GetExtDocOptions() )
143 mxExtDocOpt
= std::make_shared
<ScExtDocOptions
>( *pOldDocOpt
);
145 mxExtDocOpt
= std::make_shared
<ScExtDocOptions
>();
150 Reference
< frame::XDesktop2
> xFramesSupp
= frame::Desktop::create( ::comphelper::getProcessComponentContext() );
151 Reference
< XFrame
> xFrame( xFramesSupp
->getActiveFrame(), UNO_SET_THROW
);
152 Reference
< XDevice
> xDevice( xFrame
->getContainerWindow(), UNO_QUERY_THROW
);
153 DeviceInfo aDeviceInfo
= xDevice
->getInfo();
154 mfScreenPixelX
= (aDeviceInfo
.PixelPerMeterX
> 0) ? (100000.0 / aDeviceInfo
.PixelPerMeterX
) : 50.0;
155 mfScreenPixelY
= (aDeviceInfo
.PixelPerMeterY
> 0) ? (100000.0 / aDeviceInfo
.PixelPerMeterY
) : 50.0;
157 catch( const Exception
&)
159 TOOLS_WARN_EXCEPTION( "sc", "XclRootData::XclRootData - cannot get output device info");
163 XclRootData::~XclRootData()
167 XclRoot::XclRoot( XclRootData
& rRootData
) :
170 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
175 mrData
.mxTracer
= std::make_shared
<XclTracer
>( GetDocUrl() );
178 XclRoot::XclRoot( const XclRoot
& rRoot
) :
179 mrData( rRoot
.mrData
)
181 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
188 #if defined(DBG_UTIL) && OSL_DEBUG_LEVEL > 0
193 XclRoot
& XclRoot::operator=( const XclRoot
& rRoot
)
195 (void)rRoot
; // avoid compiler warning
196 // allowed for assignment in derived classes - but test if the same root data is used
197 OSL_ENSURE( &mrData
== &rRoot
.mrData
, "XclRoot::operator= - incompatible root data" );
201 void XclRoot::SetTextEncoding( rtl_TextEncoding eTextEnc
)
203 if( eTextEnc
!= RTL_TEXTENCODING_DONTKNOW
)
204 mrData
.meTextEnc
= eTextEnc
;
207 void XclRoot::SetCharWidth( const XclFontData
& rFontData
)
209 mrData
.mnCharWidth
= 0;
210 if( OutputDevice
* pPrinter
= GetPrinter() )
212 vcl::Font
aFont( rFontData
.maName
, Size( 0, rFontData
.mnHeight
) );
213 aFont
.SetFamily( rFontData
.GetScFamily( GetTextEncoding() ) );
214 aFont
.SetCharSet( rFontData
.GetFontEncoding() );
215 aFont
.SetWeight( rFontData
.GetScWeight() );
216 pPrinter
->SetFont( aFont
);
217 // Usually digits have the same width, but in some fonts they don't ...
218 // Match the import in sc/source/filter/oox/unitconverter.cxx
219 // UnitConverter::finalizeImport()
220 for (sal_Unicode cChar
= '0'; cChar
<= '9'; ++cChar
)
221 mrData
.mnCharWidth
= std::max( pPrinter
->GetTextWidth( OUString(cChar
)), mrData
.mnCharWidth
);
223 // Set the width of space ' ' character.
224 mrData
.mnSpaceWidth
= pPrinter
->GetTextWidth(OUString(' '));
226 if( mrData
.mnCharWidth
<= 0 )
228 // #i48717# Win98 with HP LaserJet returns 0
229 SAL_WARN( "sc", "XclRoot::SetCharWidth - invalid character width (no printer?)" );
230 mrData
.mnCharWidth
= 11 * rFontData
.mnHeight
/ 20;
232 if (mrData
.mnSpaceWidth
<= 0)
234 SAL_WARN( "sc", "XclRoot::SetCharWidth - invalid character width (no printer?)" );
235 mrData
.mnSpaceWidth
= 45;
239 sal_Int32
XclRoot::GetHmmFromPixelX( double fPixelX
) const
241 return static_cast< sal_Int32
>( fPixelX
* mrData
.mfScreenPixelX
+ 0.5 );
244 sal_Int32
XclRoot::GetHmmFromPixelY( double fPixelY
) const
246 return static_cast< sal_Int32
>( fPixelY
* mrData
.mfScreenPixelY
+ 0.5 );
249 uno::Sequence
< beans::NamedValue
> XclRoot::RequestEncryptionData( ::comphelper::IDocPasswordVerifier
& rVerifier
) const
251 ::std::vector
< OUString
> aDefaultPasswords
{ XclRootData::gaDefPassword
};
252 return ScfApiHelper::QueryEncryptionDataForMedium( mrData
.mrMedium
, rVerifier
, &aDefaultPasswords
);
255 bool XclRoot::HasVbaStorage() const
257 tools::SvRef
<SotStorage
> xRootStrg
= GetRootStorage();
258 return xRootStrg
.is() && xRootStrg
->IsContained( EXC_STORAGE_VBA_PROJECT
);
261 tools::SvRef
<SotStorage
> XclRoot::OpenStorage( tools::SvRef
<SotStorage
> const & xStrg
, const OUString
& rStrgName
) const
263 return mrData
.mbExport
?
264 ScfTools::OpenStorageWrite( xStrg
, rStrgName
) :
265 ScfTools::OpenStorageRead( xStrg
, rStrgName
);
268 tools::SvRef
<SotStorage
> XclRoot::OpenStorage( const OUString
& rStrgName
) const
270 return OpenStorage( GetRootStorage(), rStrgName
);
273 tools::SvRef
<SotStorageStream
> XclRoot::OpenStream( tools::SvRef
<SotStorage
> const & xStrg
, const OUString
& rStrmName
) const
275 return mrData
.mbExport
?
276 ScfTools::OpenStorageStreamWrite( xStrg
, rStrmName
) :
277 ScfTools::OpenStorageStreamRead( xStrg
, rStrmName
);
280 tools::SvRef
<SotStorageStream
> XclRoot::OpenStream( const OUString
& rStrmName
) const
282 return OpenStream( GetRootStorage(), rStrmName
);
285 ScDocument
& XclRoot::GetDoc() const
290 SfxObjectShell
* XclRoot::GetDocShell() const
292 return GetDoc().GetDocumentShell();
295 ScModelObj
* XclRoot::GetDocModelObj() const
297 SfxObjectShell
* pDocShell
= GetDocShell();
298 return pDocShell
? comphelper::getFromUnoTunnel
<ScModelObj
>( pDocShell
->GetModel() ) : nullptr;
301 OutputDevice
* XclRoot::GetPrinter() const
303 return GetDoc().GetRefDevice();
306 ScStyleSheetPool
& XclRoot::GetStyleSheetPool() const
308 return *GetDoc().GetStyleSheetPool();
311 ScRangeName
& XclRoot::GetNamedRanges() const
313 return *GetDoc().GetRangeName();
316 SdrPage
* XclRoot::GetSdrPage( SCTAB nScTab
) const
318 return ((nScTab
>= 0) && GetDoc().GetDrawLayer()) ?
319 GetDoc().GetDrawLayer()->GetPage( static_cast< sal_uInt16
>( nScTab
) ) : nullptr;
322 SvNumberFormatter
& XclRoot::GetFormatter() const
324 return *GetDoc().GetFormatTable();
327 DateTime
XclRoot::GetNullDate() const
329 return GetFormatter().GetNullDate();
332 sal_uInt16
XclRoot::GetBaseYear() const
334 // return 1904 for 1904-01-01, and 1900 for 1899-12-30
335 return (GetNullDate().GetYear() == 1904) ? 1904 : 1900;
338 const DateTime
theOurCompatNullDate( Date( 30, 12, 1899 ));
339 const DateTime
theExcelCutOverDate( Date( 1, 3, 1900 ));
341 double XclRoot::GetDoubleFromDateTime( const DateTime
& rDateTime
) const
343 double fValue
= rDateTime
- GetNullDate();
344 // adjust dates before 1900-03-01 to get correct time values in the range [0.0,1.0)
345 /* XXX: this is only used when reading BIFF, otherwise we'd have to check
346 * for dateCompatibility==true as mentioned below. */
347 if( rDateTime
< theExcelCutOverDate
&& GetNullDate() == theOurCompatNullDate
)
352 DateTime
XclRoot::GetDateTimeFromDouble( double fValue
) const
354 DateTime aDateTime
= GetNullDate() + fValue
;
355 // adjust dates before 1900-03-01 to get correct time values
356 /* FIXME: correction should only be done when writing BIFF or OOXML
357 * transitional with dateCompatibility==true (or absent for default true),
358 * but not if strict ISO/IEC 29500 which does not have the Excel error
359 * compatibility and the null date is the same 1899-12-30 as ours. */
360 if( aDateTime
< theExcelCutOverDate
&& GetNullDate() == theOurCompatNullDate
)
361 aDateTime
.AddDays(1);
365 ScEditEngineDefaulter
& XclRoot::GetEditEngine() const
367 if( !mrData
.mxEditEngine
)
369 mrData
.mxEditEngine
= std::make_shared
<ScEditEngineDefaulter
>( GetDoc().GetEnginePool() );
370 ScEditEngineDefaulter
& rEE
= *mrData
.mxEditEngine
;
371 rEE
.SetRefMapMode(MapMode(MapUnit::Map100thMM
));
372 rEE
.SetEditTextObjectPool( GetDoc().GetEditPool() );
373 rEE
.SetUpdateLayout( false );
374 rEE
.EnableUndo( false );
375 rEE
.SetControlWord( rEE
.GetControlWord() & ~EEControlBits::ALLOWBIGOBJS
);
377 return *mrData
.mxEditEngine
;
380 ScHeaderEditEngine
& XclRoot::GetHFEditEngine() const
382 if( !mrData
.mxHFEditEngine
)
384 mrData
.mxHFEditEngine
= std::make_shared
<ScHeaderEditEngine
>( EditEngine::CreatePool().get() );
385 ScHeaderEditEngine
& rEE
= *mrData
.mxHFEditEngine
;
386 rEE
.SetRefMapMode(MapMode(MapUnit::MapTwip
)); // headers/footers use twips as default metric
387 rEE
.SetUpdateLayout( false );
388 rEE
.EnableUndo( false );
389 rEE
.SetControlWord( rEE
.GetControlWord() & ~EEControlBits::ALLOWBIGOBJS
);
391 // set Calc header/footer defaults
392 auto pEditSet
= std::make_unique
<SfxItemSet
>( rEE
.GetEmptyItemSet() );
393 SfxItemSetFixed
<ATTR_PATTERN_START
, ATTR_PATTERN_END
> aItemSet( *GetDoc().GetPool() );
394 ScPatternAttr::FillToEditItemSet( *pEditSet
, aItemSet
);
395 // FillToEditItemSet() adjusts font height to 1/100th mm, we need twips
396 pEditSet
->Put( aItemSet
.Get( ATTR_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT
) );
397 pEditSet
->Put( aItemSet
.Get( ATTR_CJK_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK
) );
398 pEditSet
->Put( aItemSet
.Get( ATTR_CTL_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL
) );
399 rEE
.SetDefaults( std::move(pEditSet
) ); // takes ownership
401 return *mrData
.mxHFEditEngine
;
404 EditEngine
& XclRoot::GetDrawEditEngine() const
406 if( !mrData
.mxDrawEditEng
)
408 mrData
.mxDrawEditEng
= std::make_shared
<EditEngine
>( &GetDoc().GetDrawLayer()->GetItemPool() );
409 EditEngine
& rEE
= *mrData
.mxDrawEditEng
;
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: */