blob: 0ecd240d1dd7effec9ff0d8a33428ab07fd5eee6 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
#include "xlroot.hxx"
#include <com/sun/star/awt/XDevice.hpp>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/frame/XFramesSupplier.hpp>
#include <com/sun/star/i18n/ScriptType.hpp>
#include <comphelper/processfactory.hxx>
#include <vcl/svapp.hxx>
#include <svl/stritem.hxx>
#include <svl/languageoptions.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/printer.hxx>
#include <sfx2/docfile.hxx>
#include <vcl/font.hxx>
#include <editeng/editstat.hxx>
#include "scitems.hxx"
#include <editeng/eeitem.hxx>
#include "document.hxx"
#include "docpool.hxx"
#include "docuno.hxx"
#include "editutil.hxx"
#include "drwlayer.hxx"
#include "scextopt.hxx"
#include "patattr.hxx"
#include "fapihelper.hxx"
#include "xlconst.hxx"
#include "xlstyle.hxx"
#include "xlchart.hxx"
#include "xltracer.hxx"
#include <unotools/useroptions.hxx>
#include "root.hxx"
namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
using ::rtl::OUString;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::UNO_QUERY_THROW;
using ::com::sun::star::uno::UNO_SET_THROW;
using ::com::sun::star::awt::XDevice;
using ::com::sun::star::awt::DeviceInfo;
using ::com::sun::star::frame::XFrame;
using ::com::sun::star::frame::XFramesSupplier;
using ::com::sun::star::lang::XMultiServiceFactory;
using namespace ::com::sun::star;
// Global data ================================================================
#ifdef DBG_UTIL
XclDebugObjCounter::~XclDebugObjCounter()
{
DBG_ASSERT( mnObjCnt == 0, "XclDebugObjCounter::~XclDebugObjCounter - wrong root object count" );
}
#endif
// ----------------------------------------------------------------------------
XclRootData::XclRootData( XclBiff eBiff, SfxMedium& rMedium,
SotStorageRef xRootStrg, ScDocument& rDoc, rtl_TextEncoding eTextEnc, bool bExport ) :
meBiff( eBiff ),
meOutput( EXC_OUTPUT_BINARY ),
mrMedium( rMedium ),
mxRootStrg( xRootStrg ),
mrDoc( rDoc ),
maDefPassword( CREATE_STRING( "VelvetSweatshop" ) ),
meTextEnc( eTextEnc ),
meSysLang( Application::GetSettings().GetLanguage() ),
meDocLang( Application::GetSettings().GetLanguage() ),
meUILang( Application::GetSettings().GetUILanguage() ),
mnDefApiScript( ApiScriptType::LATIN ),
maScMaxPos( MAXCOL, MAXROW, MAXTAB ),
maXclMaxPos( EXC_MAXCOL2, EXC_MAXROW2, EXC_MAXTAB2 ),
maMaxPos( EXC_MAXCOL2, EXC_MAXROW2, EXC_MAXTAB2 ),
mxFontPropSetHlp( new XclFontPropSetHelper ),
mxChPropSetHlp( new XclChPropSetHelper ),
mxRD( new RootData ),//!
mfScreenPixelX( 50.0 ),
mfScreenPixelY( 50.0 ),
mnCharWidth( 110 ),
mnScTab( 0 ),
mbExport( bExport )
{
maUserName = SvtUserOptions().GetLastName();
if( maUserName.Len() == 0 )
maUserName = CREATE_STRING( "Calc" );
switch( ScGlobal::GetDefaultScriptType() )
{
case SCRIPTTYPE_LATIN: mnDefApiScript = ApiScriptType::LATIN; break;
case SCRIPTTYPE_ASIAN: mnDefApiScript = ApiScriptType::ASIAN; break;
case SCRIPTTYPE_COMPLEX: mnDefApiScript = ApiScriptType::COMPLEX; break;
default: DBG_ERRORFILE( "XclRootData::XclRootData - unknown script type" );
}
// maximum cell position
switch( meBiff )
{
case EXC_BIFF2: maXclMaxPos.Set( EXC_MAXCOL2, EXC_MAXROW2, EXC_MAXTAB2 ); break;
case EXC_BIFF3: maXclMaxPos.Set( EXC_MAXCOL3, EXC_MAXROW3, EXC_MAXTAB3 ); break;
case EXC_BIFF4: maXclMaxPos.Set( EXC_MAXCOL4, EXC_MAXROW4, EXC_MAXTAB4 ); break;
case EXC_BIFF5: maXclMaxPos.Set( EXC_MAXCOL5, EXC_MAXROW5, EXC_MAXTAB5 ); break;
case EXC_BIFF8: maXclMaxPos.Set( EXC_MAXCOL8, EXC_MAXROW8, EXC_MAXTAB8 ); break;
default: DBG_ERROR_BIFF();
}
maMaxPos.SetCol( ::std::min( maScMaxPos.Col(), maXclMaxPos.Col() ) );
maMaxPos.SetRow( ::std::min( maScMaxPos.Row(), maXclMaxPos.Row() ) );
maMaxPos.SetTab( ::std::min( maScMaxPos.Tab(), maXclMaxPos.Tab() ) );
// document URL and path
if( const SfxItemSet* pItemSet = mrMedium.GetItemSet() )
if( const SfxStringItem* pItem = static_cast< const SfxStringItem* >( pItemSet->GetItem( SID_FILE_NAME ) ) )
maDocUrl = pItem->GetValue();
maBasePath = maDocUrl.Copy( 0, maDocUrl.SearchBackward( '/' ) + 1 );
// extended document options - always own object, try to copy existing data from document
if( const ScExtDocOptions* pOldDocOpt = mrDoc.GetExtDocOptions() )
mxExtDocOpt.reset( new ScExtDocOptions( *pOldDocOpt ) );
else
mxExtDocOpt.reset( new ScExtDocOptions );
// screen pixel size
try
{
Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_SET_THROW );
Reference< XFramesSupplier > xFramesSupp( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.frame.Desktop" ) ), UNO_QUERY_THROW );
Reference< XFrame > xFrame( xFramesSupp->getActiveFrame(), UNO_SET_THROW );
Reference< XDevice > xDevice( xFrame->getContainerWindow(), UNO_QUERY_THROW );
DeviceInfo aDeviceInfo = xDevice->getInfo();
mfScreenPixelX = (aDeviceInfo.PixelPerMeterX > 0) ? (100000.0 / aDeviceInfo.PixelPerMeterX) : 50.0;
mfScreenPixelY = (aDeviceInfo.PixelPerMeterY > 0) ? (100000.0 / aDeviceInfo.PixelPerMeterY) : 50.0;
}
catch( Exception& )
{
OSL_ENSURE( false, "XclRootData::XclRootData - cannot get output device info" );
}
}
XclRootData::~XclRootData()
{
}
// ----------------------------------------------------------------------------
XclRoot::XclRoot( XclRootData& rRootData ) :
mrData( rRootData )
{
#ifdef DBG_UTIL
++mrData.mnObjCnt;
#endif
// filter tracer
// do not use CREATE_OUSTRING for conditional expression
mrData.mxTracer.reset( new XclTracer( GetDocUrl(), OUString::createFromAscii(
IsExport() ? "Office.Tracing/Export/Excel" : "Office.Tracing/Import/Excel" ) ) );
}
XclRoot::XclRoot( const XclRoot& rRoot ) :
mrData( rRoot.mrData )
{
#ifdef DBG_UTIL
++mrData.mnObjCnt;
#endif
}
XclRoot::~XclRoot()
{
#ifdef DBG_UTIL
--mrData.mnObjCnt;
#endif
}
XclRoot& XclRoot::operator=( const XclRoot& rRoot )
{
(void)rRoot; // avoid compiler warning
// allowed for assignment in derived classes - but test if the same root data is used
DBG_ASSERT( &mrData == &rRoot.mrData, "XclRoot::operator= - incompatible root data" );
return *this;
}
void XclRoot::SetTextEncoding( rtl_TextEncoding eTextEnc )
{
if( eTextEnc != RTL_TEXTENCODING_DONTKNOW )
mrData.meTextEnc = eTextEnc;
}
void XclRoot::SetCharWidth( const XclFontData& rFontData )
{
mrData.mnCharWidth = 0;
if( OutputDevice* pPrinter = GetPrinter() )
{
Font aFont( rFontData.maName, Size( 0, rFontData.mnHeight ) );
aFont.SetFamily( rFontData.GetScFamily( GetTextEncoding() ) );
aFont.SetCharSet( rFontData.GetFontEncoding() );
aFont.SetWeight( rFontData.GetScWeight() );
pPrinter->SetFont( aFont );
mrData.mnCharWidth = pPrinter->GetTextWidth( String( '0' ) );
}
if( mrData.mnCharWidth <= 0 )
{
// #i48717# Win98 with HP LaserJet returns 0
DBG_ERRORFILE( "XclRoot::SetCharWidth - invalid character width (no printer?)" );
mrData.mnCharWidth = 11 * rFontData.mnHeight / 20;
}
}
sal_Int32 XclRoot::GetHmmFromPixelX( double fPixelX ) const
{
return static_cast< sal_Int32 >( fPixelX * mrData.mfScreenPixelX + 0.5 );
}
sal_Int32 XclRoot::GetHmmFromPixelY( double fPixelY ) const
{
return static_cast< sal_Int32 >( fPixelY * mrData.mfScreenPixelY + 0.5 );
}
uno::Sequence< beans::NamedValue > XclRoot::RequestEncryptionData( ::comphelper::IDocPasswordVerifier& rVerifier ) const
{
::std::vector< OUString > aDefaultPasswords;
aDefaultPasswords.push_back( mrData.maDefPassword );
return ScfApiHelper::QueryEncryptionDataForMedium( mrData.mrMedium, rVerifier, &aDefaultPasswords );
}
bool XclRoot::HasVbaStorage() const
{
SotStorageRef xRootStrg = GetRootStorage();
return xRootStrg.Is() && xRootStrg->IsContained( EXC_STORAGE_VBA_PROJECT );
}
SotStorageRef XclRoot::OpenStorage( SotStorageRef xStrg, const String& rStrgName ) const
{
return mrData.mbExport ?
ScfTools::OpenStorageWrite( xStrg, rStrgName ) :
ScfTools::OpenStorageRead( xStrg, rStrgName );
}
SotStorageRef XclRoot::OpenStorage( const String& rStrgName ) const
{
return OpenStorage( GetRootStorage(), rStrgName );
}
SotStorageStreamRef XclRoot::OpenStream( SotStorageRef xStrg, const String& rStrmName ) const
{
return mrData.mbExport ?
ScfTools::OpenStorageStreamWrite( xStrg, rStrmName ) :
ScfTools::OpenStorageStreamRead( xStrg, rStrmName );
}
SotStorageStreamRef XclRoot::OpenStream( const String& rStrmName ) const
{
return OpenStream( GetRootStorage(), rStrmName );
}
SfxObjectShell* XclRoot::GetDocShell() const
{
return GetDoc().GetDocumentShell();
}
ScModelObj* XclRoot::GetDocModelObj() const
{
SfxObjectShell* pDocShell = GetDocShell();
return pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : 0;
}
OutputDevice* XclRoot::GetPrinter() const
{
return GetDoc().GetRefDevice();
}
ScStyleSheetPool& XclRoot::GetStyleSheetPool() const
{
return *GetDoc().GetStyleSheetPool();
}
ScRangeName& XclRoot::GetNamedRanges() const
{
return *GetDoc().GetRangeName();
}
ScDBCollection& XclRoot::GetDatabaseRanges() const
{
return *GetDoc().GetDBCollection();
}
SdrPage* XclRoot::GetSdrPage( SCTAB nScTab ) const
{
return ((nScTab >= 0) && GetDoc().GetDrawLayer()) ?
GetDoc().GetDrawLayer()->GetPage( static_cast< sal_uInt16 >( nScTab ) ) : 0;
}
SvNumberFormatter& XclRoot::GetFormatter() const
{
return *GetDoc().GetFormatTable();
}
DateTime XclRoot::GetNullDate() const
{
return *GetFormatter().GetNullDate();
}
sal_uInt16 XclRoot::GetBaseYear() const
{
// return 1904 for 1904-01-01, and 1900 for 1899-12-30
return (GetNullDate().GetYear() == 1904) ? 1904 : 1900;
}
double XclRoot::GetDoubleFromDateTime( const DateTime& rDateTime ) const
{
double fValue = rDateTime - GetNullDate();
// adjust dates before 1900-03-01 to get correct time values in the range [0.0,1.0)
if( rDateTime < DateTime( Date( 1, 3, 1900 ) ) )
fValue -= 1.0;
return fValue;
}
DateTime XclRoot::GetDateTimeFromDouble( double fValue ) const
{
DateTime aDateTime = GetNullDate() + fValue;
// adjust dates before 1900-03-01 to get correct time values
if( aDateTime < DateTime( Date( 1, 3, 1900 ) ) )
aDateTime += 1L;
return aDateTime;
}
ScEditEngineDefaulter& XclRoot::GetEditEngine() const
{
if( !mrData.mxEditEngine.get() )
{
mrData.mxEditEngine.reset( new ScEditEngineDefaulter( GetDoc().GetEnginePool() ) );
ScEditEngineDefaulter& rEE = *mrData.mxEditEngine;
rEE.SetRefMapMode( MAP_100TH_MM );
rEE.SetEditTextObjectPool( GetDoc().GetEditPool() );
rEE.SetUpdateMode( sal_False );
rEE.EnableUndo( sal_False );
rEE.SetControlWord( rEE.GetControlWord() & ~EE_CNTRL_ALLOWBIGOBJS );
}
return *mrData.mxEditEngine;
}
ScHeaderEditEngine& XclRoot::GetHFEditEngine() const
{
if( !mrData.mxHFEditEngine.get() )
{
mrData.mxHFEditEngine.reset( new ScHeaderEditEngine( EditEngine::CreatePool(), sal_True ) );
ScHeaderEditEngine& rEE = *mrData.mxHFEditEngine;
rEE.SetRefMapMode( MAP_TWIP ); // headers/footers use twips as default metric
rEE.SetUpdateMode( sal_False );
rEE.EnableUndo( sal_False );
rEE.SetControlWord( rEE.GetControlWord() & ~EE_CNTRL_ALLOWBIGOBJS );
// set Calc header/footer defaults
SfxItemSet* pEditSet = new SfxItemSet( rEE.GetEmptyItemSet() );
SfxItemSet aItemSet( *GetDoc().GetPool(), ATTR_PATTERN_START, ATTR_PATTERN_END );
ScPatternAttr::FillToEditItemSet( *pEditSet, aItemSet );
// FillToEditItemSet() adjusts font height to 1/100th mm, we need twips
pEditSet->Put( aItemSet.Get( ATTR_FONT_HEIGHT ), EE_CHAR_FONTHEIGHT );
pEditSet->Put( aItemSet.Get( ATTR_CJK_FONT_HEIGHT ), EE_CHAR_FONTHEIGHT_CJK );
pEditSet->Put( aItemSet.Get( ATTR_CTL_FONT_HEIGHT ), EE_CHAR_FONTHEIGHT_CTL );
rEE.SetDefaults( pEditSet ); // takes ownership
}
return *mrData.mxHFEditEngine;
}
EditEngine& XclRoot::GetDrawEditEngine() const
{
if( !mrData.mxDrawEditEng.get() )
{
mrData.mxDrawEditEng.reset( new EditEngine( &GetDoc().GetDrawLayer()->GetItemPool() ) );
EditEngine& rEE = *mrData.mxDrawEditEng;
rEE.SetRefMapMode( MAP_100TH_MM );
rEE.SetUpdateMode( sal_False );
rEE.EnableUndo( sal_False );
rEE.SetControlWord( rEE.GetControlWord() & ~EE_CNTRL_ALLOWBIGOBJS );
}
return *mrData.mxDrawEditEng;
}
XclFontPropSetHelper& XclRoot::GetFontPropSetHelper() const
{
return *mrData.mxFontPropSetHlp;
}
XclChPropSetHelper& XclRoot::GetChartPropSetHelper() const
{
return *mrData.mxChPropSetHlp;
}
ScExtDocOptions& XclRoot::GetExtDocOptions() const
{
return *mrData.mxExtDocOpt;
}
XclTracer& XclRoot::GetTracer() const
{
return *mrData.mxTracer;
}
// ============================================================================