| /************************************************************** |
| * |
| * 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. |
| * |
| *************************************************************/ |
| |
| |
| #include "vbafield.hxx" |
| #include "vbarange.hxx" |
| #include <com/sun/star/frame/XModel.hpp> |
| #include <com/sun/star/text/XTextViewCursorSupplier.hpp> |
| #include <com/sun/star/view/XSelectionSupplier.hpp> |
| #include <com/sun/star/text/XTextFieldsSupplier.hpp> |
| #include <ooo/vba/word/WdFieldType.hpp> |
| #include <com/sun/star/text/FilenameDisplayFormat.hpp> |
| #include <com/sun/star/util/XRefreshable.hpp> |
| #include <swtypes.hxx> |
| |
| using namespace ::ooo::vba; |
| using namespace ::com::sun::star; |
| |
| // *** SwVbaField *********************************************** |
| |
| SwVbaField::SwVbaField( const uno::Reference< ooo::vba::XHelperInterface >& rParent, const uno::Reference< uno::XComponentContext >& rContext, const css::uno::Reference< css::text::XTextDocument >& rDocument, const uno::Reference< css::text::XTextField >& xTextField) throw ( uno::RuntimeException ) : SwVbaField_BASE( rParent, rContext ), mxTextDocument( rDocument ) |
| { |
| mxTextField.set( xTextField, uno::UNO_QUERY_THROW ); |
| } |
| |
| // XHelperInterface |
| rtl::OUString& |
| SwVbaField::getServiceImplName() |
| { |
| static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaField") ); |
| return sImplName; |
| } |
| |
| uno::Sequence<rtl::OUString> |
| SwVbaField::getServiceNames() |
| { |
| static uno::Sequence< rtl::OUString > aServiceNames; |
| if ( aServiceNames.getLength() == 0 ) |
| { |
| aServiceNames.realloc( 1 ); |
| aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.Field" ) ); |
| } |
| return aServiceNames; |
| } |
| |
| // *** _ReadFieldParams *********************************************** |
| // the codes are copied from ww8par5.cxx |
| class _ReadFieldParams |
| { |
| private: |
| String aData; |
| xub_StrLen nLen, nFnd, nNext, nSavPtr; |
| String aFieldName; |
| public: |
| _ReadFieldParams( const String& rData ); |
| ~_ReadFieldParams(); |
| |
| xub_StrLen GoToTokenParam(); |
| long SkipToNextToken(); |
| xub_StrLen GetTokenSttPtr() const { return nFnd; } |
| |
| xub_StrLen FindNextStringPiece( xub_StrLen _nStart = STRING_NOTFOUND ); |
| bool GetTokenSttFromTo(xub_StrLen* _pFrom, xub_StrLen* _pTo, |
| xub_StrLen _nMax); |
| |
| String GetResult() const; |
| String GetFieldName()const { return aFieldName; } |
| }; |
| |
| |
| _ReadFieldParams::_ReadFieldParams( const String& _rData ) |
| : aData( _rData ), nLen( _rData.Len() ), nNext( 0 ) |
| { |
| /* |
| erstmal nach einer oeffnenden Klammer oder einer Leerstelle oder einem |
| Anfuehrungszeichen oder einem Backslash suchen, damit der Feldbefehl |
| (also INCLUDEPICTURE bzw EINFUeGENGRAFIK bzw ...) ueberlesen wird |
| */ |
| while( (nLen > nNext) && (aData.GetChar( nNext ) == ' ') ) |
| ++nNext; |
| |
| sal_Unicode c; |
| while( nLen > nNext |
| && (c = aData.GetChar( nNext )) != ' ' |
| && c != '"' |
| && c != '\\' |
| && c != 132 |
| && c != 0x201c ) |
| ++nNext; |
| |
| nFnd = nNext; |
| nSavPtr = nNext; |
| aFieldName = aData.Copy( 0, nFnd ); |
| // cLastChar = aData.GetChar( nSavPtr ); |
| } |
| |
| |
| _ReadFieldParams::~_ReadFieldParams() |
| { |
| // aData.SetChar( nSavPtr, cLastChar ); |
| } |
| |
| |
| String _ReadFieldParams::GetResult() const |
| { |
| return (STRING_NOTFOUND == nFnd) |
| ? aEmptyStr |
| : aData.Copy( nFnd, (nSavPtr - nFnd) ); |
| } |
| |
| |
| xub_StrLen _ReadFieldParams::GoToTokenParam() |
| { |
| xub_StrLen nOld = nNext; |
| if( -2 == SkipToNextToken() ) |
| return GetTokenSttPtr(); |
| nNext = nOld; |
| return STRING_NOTFOUND; |
| } |
| |
| // ret: -2: NOT a '\' parameter but normal Text |
| long _ReadFieldParams::SkipToNextToken() |
| { |
| long nRet = -1; // Ende |
| if ( |
| (STRING_NOTFOUND != nNext) && (nLen > nNext) && |
| STRING_NOTFOUND != (nFnd = FindNextStringPiece(nNext)) |
| ) |
| { |
| nSavPtr = nNext; |
| |
| if ('\\' == aData.GetChar(nFnd) && '\\' != aData.GetChar(nFnd + 1)) |
| { |
| nRet = aData.GetChar(++nFnd); |
| nNext = ++nFnd; // und dahinter setzen |
| } |
| else |
| { |
| nRet = -2; |
| if ( |
| (STRING_NOTFOUND != nSavPtr ) && |
| ( |
| ('"' == aData.GetChar(nSavPtr - 1)) || |
| (0x201d == aData.GetChar(nSavPtr - 1)) |
| ) |
| ) |
| { |
| --nSavPtr; |
| } |
| } |
| } |
| return nRet; |
| } |
| |
| // FindNextPara sucht naechsten Backslash-Parameter oder naechste Zeichenkette |
| // bis zum Blank oder naechsten "\" oder zum schliessenden Anfuehrungszeichen |
| // oder zum String-Ende von pStr. |
| // |
| // Ausgabe ppNext (falls ppNext != 0) Suchbeginn fuer naechsten Parameter bzw. 0 |
| // |
| // Returnwert: 0 falls String-Ende erreicht, |
| // ansonsten Anfang des Paramters bzw. der Zeichenkette |
| // |
| xub_StrLen _ReadFieldParams::FindNextStringPiece(const xub_StrLen nStart) |
| { |
| xub_StrLen n = ( STRING_NOTFOUND == nStart ) ? nFnd : nStart; // Anfang |
| xub_StrLen n2; // Ende |
| |
| nNext = STRING_NOTFOUND; // Default fuer nicht gefunden |
| |
| while( (nLen > n) && (aData.GetChar( n ) == ' ') ) |
| ++n; |
| |
| if( nLen == n ) |
| return STRING_NOTFOUND; // String End reached! |
| |
| if( (aData.GetChar( n ) == '"') // Anfuehrungszeichen vor Para? |
| || (aData.GetChar( n ) == 0x201c) |
| || (aData.GetChar( n ) == 132) ) |
| { |
| n++; // Anfuehrungszeichen ueberlesen |
| n2 = n; // ab hier nach Ende suchen |
| while( (nLen > n2) |
| && (aData.GetChar( n2 ) != '"') |
| && (aData.GetChar( n2 ) != 0x201d) |
| && (aData.GetChar( n2 ) != 147) ) |
| n2++; // Ende d. Paras suchen |
| } |
| else // keine Anfuehrungszeichen |
| { |
| n2 = n; // ab hier nach Ende suchen |
| while( (nLen > n2) && (aData.GetChar( n2 ) != ' ') ) // Ende d. Paras suchen |
| { |
| if( aData.GetChar( n2 ) == '\\' ) |
| { |
| if( aData.GetChar( n2+1 ) == '\\' ) |
| n2 += 2; // Doppel-Backslash -> OK |
| else |
| { |
| if( n2 > n ) |
| n2--; |
| break; // einfach-Backslash -> Ende |
| } |
| } |
| else |
| n2++; // kein Backslash -> OK |
| } |
| } |
| if( nLen > n2 ) |
| { |
| if(aData.GetChar( n2 ) != ' ') n2++; |
| nNext = n2; |
| } |
| return n; |
| } |
| |
| |
| |
| // read parameters "1-3" or 1-3 with both values between 1 and nMax |
| bool _ReadFieldParams::GetTokenSttFromTo(sal_uInt16* pFrom, sal_uInt16* pTo, sal_uInt16 nMax) |
| { |
| sal_uInt16 nStart = 0; |
| sal_uInt16 nEnd = 0; |
| xub_StrLen n = GoToTokenParam(); |
| if( STRING_NOTFOUND != n ) |
| { |
| |
| String sParams( GetResult() ); |
| |
| xub_StrLen nIndex = 0; |
| String sStart( sParams.GetToken(0, '-', nIndex) ); |
| if( STRING_NOTFOUND != nIndex ) |
| { |
| nStart = static_cast<sal_uInt16>(sStart.ToInt32()); |
| nEnd = static_cast<sal_uInt16>(sParams.Copy(nIndex).ToInt32()); |
| } |
| } |
| if( pFrom ) *pFrom = nStart; |
| if( pTo ) *pTo = nEnd; |
| |
| return nStart && nEnd && (nMax >= nStart) && (nMax >= nEnd); |
| } |
| |
| // *** SwVbaFields *********************************************** |
| |
| uno::Any lcl_createField( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel, const uno::Any& aSource ) |
| { |
| uno::Reference< text::XTextField > xTextField( aSource, uno::UNO_QUERY_THROW ); |
| uno::Reference< text::XTextDocument > xTextDocument( xModel, uno::UNO_QUERY_THROW ); |
| uno::Reference< word::XField > xField( new SwVbaField( xParent, xContext, xTextDocument, xTextField ) ); |
| return uno::makeAny( xField ); |
| } |
| |
| typedef ::cppu::WeakImplHelper1< css::container::XEnumeration > FieldEnumeration_BASE; |
| typedef ::cppu::WeakImplHelper2< container::XIndexAccess, container::XEnumerationAccess > FieldCollectionHelper_BASE; |
| |
| class FieldEnumeration : public FieldEnumeration_BASE |
| { |
| uno::Reference< XHelperInterface > mxParent; |
| uno::Reference< uno::XComponentContext > mxContext; |
| uno::Reference< frame::XModel > mxModel; |
| uno::Reference< container::XEnumeration > mxEnumeration; |
| public: |
| FieldEnumeration( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext > & xContext, const uno::Reference< frame::XModel >& xModel, const uno::Reference< container::XEnumeration >& xEnumeration ) : mxParent( xParent ), mxContext( xContext ), mxModel( xModel ), mxEnumeration( xEnumeration ) |
| { |
| } |
| virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (uno::RuntimeException) |
| { |
| return mxEnumeration->hasMoreElements(); |
| } |
| virtual uno::Any SAL_CALL nextElement( ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) |
| { |
| if ( !hasMoreElements() ) |
| throw container::NoSuchElementException(); |
| return lcl_createField( mxParent, mxContext, mxModel, mxEnumeration->nextElement() ); |
| } |
| }; |
| |
| class FieldCollectionHelper : public FieldCollectionHelper_BASE |
| { |
| uno::Reference< XHelperInterface > mxParent; |
| uno::Reference< uno::XComponentContext > mxContext; |
| uno::Reference< frame::XModel > mxModel; |
| uno::Reference< container::XEnumerationAccess > mxEnumerationAccess; |
| public: |
| FieldCollectionHelper( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel ) throw (css::uno::RuntimeException) : mxParent( xParent ), mxContext( xContext ), mxModel( xModel ) |
| { |
| uno::Reference< text::XTextFieldsSupplier > xSupp( xModel, uno::UNO_QUERY_THROW ); |
| mxEnumerationAccess.set( xSupp->getTextFields(), uno::UNO_QUERY_THROW ); |
| } |
| // XElementAccess |
| virtual uno::Type SAL_CALL getElementType( ) throw (uno::RuntimeException) { return mxEnumerationAccess->getElementType(); } |
| virtual ::sal_Bool SAL_CALL hasElements( ) throw (uno::RuntimeException) { return mxEnumerationAccess->hasElements(); } |
| // XIndexAccess |
| virtual ::sal_Int32 SAL_CALL getCount( ) throw (uno::RuntimeException) |
| { |
| uno::Reference< container::XEnumeration > xEnumeration = mxEnumerationAccess->createEnumeration(); |
| sal_Int32 nCount = 0; |
| while( xEnumeration->hasMoreElements() ) |
| { |
| ++nCount; |
| xEnumeration->nextElement(); |
| } |
| return nCount; |
| } |
| virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException ) |
| { |
| if( Index < 0 || Index >= getCount() ) |
| throw lang::IndexOutOfBoundsException(); |
| |
| uno::Reference< container::XEnumeration > xEnumeration = mxEnumerationAccess->createEnumeration(); |
| sal_Int32 nCount = 0; |
| while( xEnumeration->hasMoreElements() ) |
| { |
| if( nCount == Index ) |
| { |
| return xEnumeration->nextElement(); |
| } |
| ++nCount; |
| } |
| throw lang::IndexOutOfBoundsException(); |
| } |
| // XEnumerationAccess |
| virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) throw (uno::RuntimeException) |
| { |
| uno::Reference< container::XEnumeration > xEnumeration = mxEnumerationAccess->createEnumeration(); |
| return uno::Reference< container::XEnumeration >( new FieldEnumeration( mxParent, mxContext, mxModel, xEnumeration ) ); |
| } |
| }; |
| |
| SwVbaFields::SwVbaFields( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext > & xContext, const uno::Reference< frame::XModel >& xModel ) : SwVbaFields_BASE( xParent, xContext , uno::Reference< container::XIndexAccess >( new FieldCollectionHelper( xParent, xContext, xModel ) ) ), mxModel( xModel ) |
| { |
| mxMSF.set( mxModel, uno::UNO_QUERY_THROW ); |
| } |
| |
| uno::Reference< word::XField > SAL_CALL |
| SwVbaFields::Add( const css::uno::Reference< ::ooo::vba::word::XRange >& Range, const css::uno::Any& Type, const css::uno::Any& Text, const css::uno::Any& /*PreserveFormatting*/ ) throw (css::uno::RuntimeException) |
| { |
| sal_Int32 nType = word::WdFieldType::wdFieldEmpty; |
| Type >>= nType; |
| rtl::OUString sText; |
| Text >>= sText; |
| |
| String sFieldName; |
| if( ( nType == word::WdFieldType::wdFieldEmpty ) && ( sText.getLength() > 0 ) ) |
| { |
| _ReadFieldParams aReadParam(sText); |
| sFieldName = aReadParam.GetFieldName(); |
| } |
| |
| uno::Reference< text::XTextContent > xTextField; |
| if( nType == word::WdFieldType::wdFieldFileName || sFieldName.EqualsIgnoreCaseAscii("FILENAME") ) |
| { |
| xTextField.set( Create_Field_FileName( sText ), uno::UNO_QUERY_THROW ); |
| } |
| else |
| { |
| throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference< uno::XInterface >() ); |
| } |
| |
| SwVbaRange* pVbaRange = dynamic_cast< SwVbaRange* >( Range.get() ); |
| uno::Reference< text::XTextRange > xTextRange = pVbaRange->getXTextRange(); |
| uno::Reference< text::XText > xText = xTextRange->getText(); |
| xText->insertTextContent( xTextRange, xTextField, true ); |
| return uno::Reference< word::XField >( new SwVbaField( mxParent, mxContext, uno::Reference< text::XTextDocument >( mxModel, uno::UNO_QUERY_THROW ), uno::Reference< text::XTextField >( xTextField, uno::UNO_QUERY_THROW ) ) ); |
| } |
| |
| uno::Reference< text::XTextField > SwVbaFields::Create_Field_FileName( const rtl::OUString _text ) throw (uno::RuntimeException) |
| { |
| uno::Reference< text::XTextField > xTextField( mxMSF->createInstance( rtl::OUString::createFromAscii("com.sun.star.text.TextField.FileName") ), uno::UNO_QUERY_THROW ); |
| sal_Int16 nFileFormat = text::FilenameDisplayFormat::NAME_AND_EXT; |
| if( _text.getLength() > 0 ) |
| { |
| long nRet; |
| _ReadFieldParams aReadParam( _text ); |
| while (-1 != (nRet = aReadParam.SkipToNextToken())) |
| { |
| switch (nRet) |
| { |
| case 'p': |
| nFileFormat = text::FilenameDisplayFormat::FULL; |
| break; |
| case '*': |
| //Skip over MERGEFORMAT |
| aReadParam.SkipToNextToken(); |
| break; |
| default: |
| DebugHelper::exception(SbERR_BAD_ARGUMENT, rtl::OUString()); |
| break; |
| } |
| } |
| } |
| |
| uno::Reference< beans::XPropertySet > xProps( xTextField, uno::UNO_QUERY_THROW ); |
| xProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FileFormat") ), uno::makeAny( nFileFormat ) ); |
| |
| return xTextField; |
| } |
| |
| uno::Reference< container::XEnumeration > SAL_CALL |
| SwVbaFields::createEnumeration() throw (uno::RuntimeException) |
| { |
| uno::Reference< container::XEnumerationAccess > xEnumerationAccess( m_xIndexAccess, uno::UNO_QUERY_THROW ); |
| return xEnumerationAccess->createEnumeration(); |
| } |
| |
| // ScVbaCollectionBaseImpl |
| uno::Any |
| SwVbaFields::createCollectionObject( const uno::Any& aSource ) |
| { |
| return lcl_createField( mxParent, mxContext, mxModel, aSource ); |
| } |
| |
| sal_Int32 SAL_CALL SwVbaFields::Update() throw (uno::RuntimeException) |
| { |
| sal_Int32 nUpdate = 1; |
| try |
| { |
| uno::Reference< text::XTextFieldsSupplier > xSupp( mxModel, uno::UNO_QUERY_THROW ); |
| uno::Reference< util::XRefreshable > xRef( xSupp->getTextFields(), uno::UNO_QUERY_THROW ); |
| xRef->refresh(); |
| nUpdate = 0; |
| }catch( uno::Exception ) |
| { |
| nUpdate = 1; |
| } |
| return nUpdate; |
| } |
| |
| // XHelperInterface |
| rtl::OUString& |
| SwVbaFields::getServiceImplName() |
| { |
| static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaFields") ); |
| return sImplName; |
| } |
| |
| // XEnumerationAccess |
| uno::Type SAL_CALL |
| SwVbaFields::getElementType() throw (uno::RuntimeException) |
| { |
| return word::XField::static_type(0); |
| } |
| |
| uno::Sequence<rtl::OUString> |
| SwVbaFields::getServiceNames() |
| { |
| static uno::Sequence< rtl::OUString > aServiceNames; |
| if ( aServiceNames.getLength() == 0 ) |
| { |
| aServiceNames.realloc( 1 ); |
| aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.Fields" ) ); |
| } |
| return aServiceNames; |
| } |
| |