/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cellvaluebinding.hxx" #include "celllistsource.hxx" #include #include #include #include // Support creation of GraphicStorageHandler and EmbeddedObjectResolver #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; #if HAVE_FEATURE_SCRIPTING static bool isInVBAMode( ScDocShell& rDocSh ) { uno::Reference xLibContainer = rDocSh.GetBasicContainer(); uno::Reference xVBACompat( xLibContainer, uno::UNO_QUERY ); if ( xVBACompat.is() ) return xVBACompat->getVBACompatibilityMode(); return false; } #endif namespace { #if HAVE_FEATURE_SCRIPTING class ScVbaObjectForCodeNameProvider : public ::cppu::WeakImplHelper< container::XNameAccess > { uno::Any maWorkbook; uno::Any maCachedObject; ScDocShell* mpDocShell; public: explicit ScVbaObjectForCodeNameProvider( ScDocShell* pDocShell ) : mpDocShell( pDocShell ) { uno::Sequence< uno::Any > aArgs{ // access the application object ( parent for workbook ) uno::Any(ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.Application", {} )), uno::Any(uno::Reference(static_cast(mpDocShell->GetModel()))) }; maWorkbook <<= ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.excel.Workbook", aArgs ); } virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override { SolarMutexGuard aGuard; maCachedObject = uno::Any(); // clear cached object ScDocument& rDoc = mpDocShell->GetDocument(); // aName is generated from the stream name which can be different ( case-wise ) // from the code name if( aName.equalsIgnoreAsciiCase( rDoc.GetCodeName() ) ) maCachedObject = maWorkbook; else { OUString sCodeName; SCTAB nCount = rDoc.GetTableCount(); for( SCTAB i = 0; i < nCount; i++ ) { rDoc.GetCodeName( i, sCodeName ); // aName is generated from the stream name which can be different ( case-wise ) // from the code name if( sCodeName.equalsIgnoreAsciiCase( aName ) ) { OUString sSheetName; if( rDoc.GetName( i, sSheetName ) ) { rtl::Reference< ScModelObj > xSpreadDoc( mpDocShell->GetModel() ); uno::Reference xSheets( xSpreadDoc->getSheets(), uno::UNO_SET_THROW ); uno::Reference< container::XIndexAccess > xIndexAccess( xSheets, uno::UNO_QUERY_THROW ); uno::Reference< sheet::XSpreadsheet > xSheet( xIndexAccess->getByIndex( i ), uno::UNO_QUERY_THROW ); uno::Sequence< uno::Any > aArgs{ maWorkbook, uno::Any(uno::Reference< frame::XModel >(xSpreadDoc)), uno::Any(sSheetName) }; // use the convenience function maCachedObject <<= ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.excel.Worksheet", aArgs ); break; } } } } return maCachedObject.hasValue(); } css::uno::Any SAL_CALL getByName( const OUString& aName ) override { SolarMutexGuard aGuard; if ( !hasByName( aName ) ) throw css::container::NoSuchElementException(); return maCachedObject; } virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override { SolarMutexGuard aGuard; ScDocument& rDoc = mpDocShell->GetDocument(); SCTAB nCount = rDoc.GetTableCount(); uno::Sequence< OUString > aNames( nCount + 1 ); auto pNames = aNames.getArray(); SCTAB index = 0; OUString sCodeName; for( ; index < nCount; ++index ) { rDoc.GetCodeName( index, sCodeName ); pNames[ index ] = sCodeName; } pNames[ index ] = rDoc.GetCodeName(); return aNames; } // XElemenAccess virtual css::uno::Type SAL_CALL getElementType( ) override { return uno::Type(); } virtual sal_Bool SAL_CALL hasElements( ) override { return true; } }; class ScVbaCodeNameProvider : public ::cppu::WeakImplHelper< document::XCodeNameQuery > { ScDocShell& mrDocShell; public: explicit ScVbaCodeNameProvider( ScDocShell& rDocShell ) : mrDocShell(rDocShell) {} // XCodeNameQuery OUString SAL_CALL getCodeNameForObject( const uno::Reference< uno::XInterface >& xIf ) override { SolarMutexGuard aGuard; OUString sCodeName; // need to find the page ( and index ) for this control uno::Reference< container::XIndexAccess > xIndex( mrDocShell.GetModel()->getDrawPages(), uno::UNO_QUERY_THROW ); sal_Int32 nLen = xIndex->getCount(); bool bMatched = false; for ( sal_Int32 index = 0; index < nLen; ++index ) { try { uno::Reference< form::XFormsSupplier > xFormSupplier( xIndex->getByIndex( index ), uno::UNO_QUERY_THROW ); uno::Reference< container::XIndexAccess > xFormIndex( xFormSupplier->getForms(), uno::UNO_QUERY_THROW ); // get the www-standard container uno::Reference< container::XIndexAccess > xFormControls( xFormIndex->getByIndex(0), uno::UNO_QUERY_THROW ); sal_Int32 nCntrls = xFormControls->getCount(); for( sal_Int32 cIndex = 0; cIndex < nCntrls; ++cIndex ) { uno::Reference< uno::XInterface > xControl( xFormControls->getByIndex( cIndex ), uno::UNO_QUERY_THROW ); bMatched = ( xControl == xIf ); if ( bMatched ) { OUString sName; mrDocShell.GetDocument().GetCodeName( static_cast( index ), sName ); sCodeName = sName; } } } catch( uno::Exception& ) {} if ( bMatched ) break; } // Probably should throw here ( if !bMatched ) return sCodeName; } OUString SAL_CALL getCodeNameForContainer( const uno::Reference& xContainer ) override { SolarMutexGuard aGuard; uno::Reference xIndex(mrDocShell.GetModel()->getDrawPages(), uno::UNO_QUERY_THROW); for (sal_Int32 i = 0, n = xIndex->getCount(); i < n; ++i) { try { uno::Reference xFormSupplier(xIndex->getByIndex(i), uno::UNO_QUERY_THROW); uno::Reference xFormIndex(xFormSupplier->getForms(), uno::UNO_QUERY_THROW); // get the www-standard container uno::Reference xFormControls(xFormIndex->getByIndex(0), uno::UNO_QUERY_THROW); if (xFormControls == xContainer) { OUString aName; if (mrDocShell.GetDocument().GetCodeName(static_cast(i), aName)) return aName; } } catch( uno::Exception& ) {} } return OUString(); } }; #endif using Type = ScServiceProvider::Type; struct ProvNamesId_Type { OUString pName; ScServiceProvider::Type nType; }; const ProvNamesId_Type aProvNamesId[] = { { "com.sun.star.sheet.Spreadsheet", Type::SHEET }, { "com.sun.star.text.TextField.URL", Type::URLFIELD }, { "com.sun.star.text.TextField.PageNumber", Type::PAGEFIELD }, { "com.sun.star.text.TextField.PageCount", Type::PAGESFIELD }, { "com.sun.star.text.TextField.Date", Type::DATEFIELD }, { "com.sun.star.text.TextField.Time", Type::TIMEFIELD }, { "com.sun.star.text.TextField.DateTime", Type::EXT_TIMEFIELD }, { "com.sun.star.text.TextField.DocInfo.Title", Type::TITLEFIELD }, { "com.sun.star.text.TextField.FileName", Type::FILEFIELD }, { "com.sun.star.text.TextField.SheetName", Type::SHEETFIELD }, { "com.sun.star.style.CellStyle", Type::CELLSTYLE }, { "com.sun.star.style.PageStyle", Type::PAGESTYLE }, { "com.sun.star.style.GraphicStyle", Type::GRAPHICSTYLE }, { "com.sun.star.sheet.TableAutoFormat", Type::AUTOFORMAT }, { "com.sun.star.sheet.TableAutoFormats", Type::AUTOFORMATS }, { "com.sun.star.sheet.SheetCellRanges", Type::CELLRANGES }, { "com.sun.star.sheet.FunctionDescriptions", Type::FUNCTIONDESCRIPTIONS }, { "com.sun.star.sheet.GlobalSheetSettings", Type::GLOBALSHEETSETTINGS }, { "com.sun.star.sheet.RecentFunctions", Type::RECENTFUNCTIONS }, { "com.sun.star.drawing.GradientTable", Type::GRADTAB }, { "com.sun.star.drawing.HatchTable", Type::HATCHTAB }, { "com.sun.star.drawing.BitmapTable", Type::BITMAPTAB }, { "com.sun.star.drawing.TransparencyGradientTable", Type::TRGRADTAB }, { "com.sun.star.drawing.MarkerTable", Type::MARKERTAB }, { "com.sun.star.drawing.DashTable", Type::DASHTAB }, { "com.sun.star.text.NumberingRules", Type::NUMRULES }, { "com.sun.star.sheet.Defaults", Type::DOCDEFLTS }, { "com.sun.star.drawing.Defaults", Type::DRAWDEFLTS }, { "com.sun.star.comp.SpreadsheetSettings", Type::DOCSPRSETT }, { "com.sun.star.document.Settings", Type::DOCCONF }, { "com.sun.star.image.ImageMapRectangleObject", Type::IMAP_RECT }, { "com.sun.star.image.ImageMapCircleObject", Type::IMAP_CIRC }, { "com.sun.star.image.ImageMapPolygonObject", Type::IMAP_POLY }, // Support creation of GraphicStorageHandler and EmbeddedObjectResolver { "com.sun.star.document.ExportGraphicStorageHandler", Type::EXPORT_GRAPHIC_STORAGE_HANDLER }, { "com.sun.star.document.ImportGraphicStorageHandler", Type::IMPORT_GRAPHIC_STORAGE_HANDLER }, { "com.sun.star.document.ExportEmbeddedObjectResolver", Type::EXPORT_EOR }, { "com.sun.star.document.ImportEmbeddedObjectResolver", Type::IMPORT_EOR }, { SC_SERVICENAME_VALBIND, Type::VALBIND }, { SC_SERVICENAME_LISTCELLBIND, Type::LISTCELLBIND }, { SC_SERVICENAME_LISTSOURCE, Type::LISTSOURCE }, { SC_SERVICENAME_CELLADDRESS, Type::CELLADDRESS }, { SC_SERVICENAME_RANGEADDRESS, Type::RANGEADDRESS }, { "com.sun.star.sheet.DocumentSettings",Type::SHEETDOCSET }, { SC_SERVICENAME_CHDATAPROV, Type::CHDATAPROV }, { SC_SERVICENAME_CHART_PIVOTTABLE_DATAPROVIDER, Type::CHART_PIVOTTABLE_DATAPROVIDER }, { SC_SERVICENAME_FORMULAPARS, Type::FORMULAPARS }, { SC_SERVICENAME_OPCODEMAPPER, Type::OPCODEMAPPER }, { "ooo.vba.VBAObjectModuleObjectProvider", Type::VBAOBJECTPROVIDER }, { "ooo.vba.VBACodeNameProvider", Type::VBACODENAMEPROVIDER }, { "ooo.vba.VBAGlobals", Type::VBAGLOBALS }, // case-correct versions of the service names (#i102468#) { "com.sun.star.text.textfield.URL", Type::URLFIELD }, { "com.sun.star.text.textfield.PageNumber", Type::PAGEFIELD }, { "com.sun.star.text.textfield.PageCount", Type::PAGESFIELD }, { "com.sun.star.text.textfield.Date", Type::DATEFIELD }, { "com.sun.star.text.textfield.Time", Type::TIMEFIELD }, { "com.sun.star.text.textfield.DateTime", Type::EXT_TIMEFIELD }, { "com.sun.star.text.textfield.docinfo.Title", Type::TITLEFIELD }, { "com.sun.star.text.textfield.FileName", Type::FILEFIELD }, { "com.sun.star.text.textfield.SheetName", Type::SHEETFIELD }, { "ooo.vba.VBAGlobals", Type::VBAGLOBALS }, }; // old service names that were in 567 still work in createInstance, // in case some macro is still using them const ProvNamesId_Type aOldNames[] = { { "stardiv.one.text.TextField.URL", Type::URLFIELD }, { "stardiv.one.text.TextField.PageNumber", Type::PAGEFIELD }, { "stardiv.one.text.TextField.PageCount", Type::PAGESFIELD }, { "stardiv.one.text.TextField.Date", Type::DATEFIELD }, { "stardiv.one.text.TextField.Time", Type::TIMEFIELD }, { "stardiv.one.text.TextField.DocumentTitle", Type::TITLEFIELD }, { "stardiv.one.text.TextField.FileName", Type::FILEFIELD }, { "stardiv.one.text.TextField.SheetName", Type::SHEETFIELD }, { "stardiv.one.style.CellStyle", Type::CELLSTYLE }, { "stardiv.one.style.PageStyle", Type::PAGESTYLE }, }; sal_Int32 getFieldType(ScServiceProvider::Type nOldType) { switch (nOldType) { case Type::URLFIELD: return text::textfield::Type::URL; case Type::PAGEFIELD: return text::textfield::Type::PAGE; case Type::PAGESFIELD: return text::textfield::Type::PAGES; case Type::DATEFIELD: return text::textfield::Type::DATE; case Type::TIMEFIELD: return text::textfield::Type::TIME; case Type::EXT_TIMEFIELD: return text::textfield::Type::EXTENDED_TIME; case Type::TITLEFIELD: return text::textfield::Type::DOCINFO_TITLE; case Type::FILEFIELD: return text::textfield::Type::EXTENDED_FILE; case Type::SHEETFIELD: return text::textfield::Type::TABLE; default: ; } return text::textfield::Type::URL; // default to URL for no reason whatsoever. } } // namespace ScServiceProvider::Type ScServiceProvider::GetProviderType(std::u16string_view rServiceName) { if (!rServiceName.empty()) { for (const ProvNamesId_Type & i : aProvNamesId) { if (rServiceName == i.pName) { return i.nType; } } for (const ProvNamesId_Type & rOldName : aOldNames) { if (rServiceName == rOldName.pName) { OSL_FAIL("old service name used"); return rOldName.nType; } } } return Type::INVALID; } uno::Reference ScServiceProvider::MakeInstance( Type nType, ScDocShell* pDocShell ) { uno::Reference xRet; switch (nType) { case Type::SHEET: // not inserted yet - DocShell=Null xRet.set(static_cast(new ScTableSheetObj(nullptr,0))); break; case Type::URLFIELD: case Type::PAGEFIELD: case Type::PAGESFIELD: case Type::DATEFIELD: case Type::TIMEFIELD: case Type::EXT_TIMEFIELD: case Type::TITLEFIELD: case Type::FILEFIELD: case Type::SHEETFIELD: { uno::Reference xNullContent; xRet.set(static_cast( new ScEditFieldObj(xNullContent, nullptr, getFieldType(nType), ESelection()))); } break; case Type::CELLSTYLE: xRet.set(static_cast(new ScStyleObj( nullptr, SfxStyleFamily::Para, OUString() ))); break; case Type::PAGESTYLE: xRet.set(static_cast(new ScStyleObj( nullptr, SfxStyleFamily::Page, OUString() ))); break; case Type::GRAPHICSTYLE: if (pDocShell) { pDocShell->MakeDrawLayer(); xRet.set(static_cast(new ScStyleObj( nullptr, SfxStyleFamily::Frame, OUString() ))); } break; case Type::AUTOFORMAT: xRet.set(static_cast(new ScAutoFormatObj( SC_AFMTOBJ_INVALID ))); break; case Type::AUTOFORMATS: xRet.set(static_cast(new ScAutoFormatsObj())); break; case Type::CELLRANGES: // isn't inserted, rather filled // -> DocShell must be set, but empty ranges if (pDocShell) xRet.set(static_cast(new ScCellRangesObj( pDocShell, ScRangeList() ))); break; case Type::FUNCTIONDESCRIPTIONS: xRet.set(static_cast(new ScFunctionListObj())); break; case Type::GLOBALSHEETSETTINGS: xRet.set(static_cast(new ScSpreadsheetSettings())); break; case Type::RECENTFUNCTIONS: xRet.set(static_cast(new ScRecentFunctionsObj())); break; case Type::DOCDEFLTS: if (pDocShell) xRet.set(static_cast(new ScDocDefaultsObj( pDocShell ))); break; case Type::DRAWDEFLTS: if (pDocShell) xRet.set(static_cast(new ScDrawDefaultsObj( pDocShell ))); break; // Drawing layer tables are not in SvxUnoDrawMSFactory, // because SvxUnoDrawMSFactory doesn't have a SdrModel pointer. // Drawing layer is always allocated if not there (MakeDrawLayer). case Type::GRADTAB: if (pDocShell) xRet.set(SvxUnoGradientTable_createInstance( pDocShell->MakeDrawLayer() )); break; case Type::HATCHTAB: if (pDocShell) xRet.set(SvxUnoHatchTable_createInstance( pDocShell->MakeDrawLayer() )); break; case Type::BITMAPTAB: if (pDocShell) xRet.set(SvxUnoBitmapTable_createInstance( pDocShell->MakeDrawLayer() )); break; case Type::TRGRADTAB: if (pDocShell) xRet.set(SvxUnoTransGradientTable_createInstance( pDocShell->MakeDrawLayer() )); break; case Type::MARKERTAB: if (pDocShell) xRet.set(SvxUnoMarkerTable_createInstance( pDocShell->MakeDrawLayer() )); break; case Type::DASHTAB: if (pDocShell) xRet.set(SvxUnoDashTable_createInstance( pDocShell->MakeDrawLayer() )); break; case Type::NUMRULES: if (pDocShell) xRet.set(SvxCreateNumRule( pDocShell->MakeDrawLayer() )); break; case Type::DOCSPRSETT: case Type::SHEETDOCSET: case Type::DOCCONF: if (pDocShell) xRet.set(static_cast(new ScDocumentConfiguration(pDocShell))); break; case Type::IMAP_RECT: xRet.set(SvUnoImageMapRectangleObject_createInstance( ScShapeObj::GetSupportedMacroItems() )); break; case Type::IMAP_CIRC: xRet.set(SvUnoImageMapCircleObject_createInstance( ScShapeObj::GetSupportedMacroItems() )); break; case Type::IMAP_POLY: xRet.set(SvUnoImageMapPolygonObject_createInstance( ScShapeObj::GetSupportedMacroItems() )); break; // Support creation of GraphicStorageHandler and EmbeddedObjectResolver case Type::EXPORT_GRAPHIC_STORAGE_HANDLER: xRet.set(getXWeak(new SvXMLGraphicHelper( SvXMLGraphicHelperMode::Write ))); break; case Type::IMPORT_GRAPHIC_STORAGE_HANDLER: xRet.set(getXWeak(new SvXMLGraphicHelper( SvXMLGraphicHelperMode::Read ))); break; case Type::EXPORT_EOR: if (pDocShell) xRet.set(getXWeak(new SvXMLEmbeddedObjectHelper( *pDocShell, SvXMLEmbeddedObjectHelperMode::Write ))); break; case Type::IMPORT_EOR: if (pDocShell) xRet.set(getXWeak(new SvXMLEmbeddedObjectHelper( *pDocShell, SvXMLEmbeddedObjectHelperMode::Read ))); break; case Type::VALBIND: case Type::LISTCELLBIND: if (pDocShell) { bool bListPos = ( nType == Type::LISTCELLBIND ); uno::Reference xDoc( pDocShell->GetBaseModel(), uno::UNO_QUERY ); xRet.set(*new calc::OCellValueBinding( xDoc, bListPos )); } break; case Type::LISTSOURCE: if (pDocShell) { uno::Reference xDoc( pDocShell->GetBaseModel(), uno::UNO_QUERY ); xRet.set(*new calc::OCellListSource( xDoc )); } break; case Type::CELLADDRESS: case Type::RANGEADDRESS: if (pDocShell) { bool bIsRange = ( nType == Type::RANGEADDRESS ); xRet.set(*new ScAddressConversionObj( pDocShell, bIsRange )); } break; case Type::CHDATAPROV: if (pDocShell) xRet = *new ScChart2DataProvider( &pDocShell->GetDocument() ); break; case Type::CHART_PIVOTTABLE_DATAPROVIDER: if (pDocShell) xRet = *new sc::PivotTableDataProvider(pDocShell->GetDocument()); break; case Type::FORMULAPARS: if (pDocShell) xRet.set(static_cast(new ScFormulaParserObj( pDocShell ))); break; case Type::OPCODEMAPPER: if (pDocShell) { ScDocument& rDoc = pDocShell->GetDocument(); ScAddress aAddress; ScCompiler* pComp = new ScCompiler(rDoc, aAddress, rDoc.GetGrammar()); xRet.set(static_cast(new ScFormulaOpCodeMapperObj(::std::unique_ptr (pComp)))); break; } break; #if HAVE_FEATURE_SCRIPTING case Type::VBAOBJECTPROVIDER: if (pDocShell && pDocShell->GetDocument().IsInVBAMode()) { xRet.set(static_cast(new ScVbaObjectForCodeNameProvider( pDocShell ))); } break; case Type::VBACODENAMEPROVIDER: if ( pDocShell && isInVBAMode( *pDocShell ) ) { xRet.set(static_cast(new ScVbaCodeNameProvider(*pDocShell))); } break; case Type::VBAGLOBALS: if (pDocShell) { uno::Any aGlobs; if ( !pDocShell->GetBasicManager()->GetGlobalUNOConstant( "VBAGlobals", aGlobs ) ) { uno::Sequence< uno::Any > aArgs{ uno::Any(uno::Reference(static_cast(pDocShell->GetModel()))) }; xRet = ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( "ooo.vba.excel.Globals", aArgs ); pDocShell->GetBasicManager()->SetGlobalUNOConstant( "VBAGlobals", uno::Any( xRet ) ); BasicManager* pAppMgr = SfxApplication::GetBasicManager(); if ( pAppMgr ) pAppMgr->SetGlobalUNOConstant( "ThisExcelDoc", aArgs[ 0 ] ); // create the VBA document event processor uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( ::ooo::vba::createVBAUnoAPIServiceWithArgs( pDocShell, "com.sun.star.script.vba.VBASpreadsheetEventProcessor", aArgs ), uno::UNO_QUERY ); pDocShell->GetDocument().SetVbaEventProcessor( xVbaEvents ); } } break; #endif default: break; } return xRet; } uno::Sequence ScServiceProvider::GetAllServiceNames() { const sal_uInt16 nEntries = SAL_N_ELEMENTS(aProvNamesId); uno::Sequence aRet(nEntries); OUString* pArray = aRet.getArray(); for (sal_uInt16 i = 0; i < nEntries; i++) { pArray[i] = aProvNamesId[i].pName; } return aRet; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */