1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #include "vbafield.hxx"
31 #include "vbarange.hxx"
32 #include <com/sun/star/frame/XModel.hpp>
33 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
34 #include <com/sun/star/view/XSelectionSupplier.hpp>
35 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
36 #include <ooo/vba/word/WdFieldType.hpp>
37 #include <com/sun/star/text/FilenameDisplayFormat.hpp>
38 #include <com/sun/star/util/XRefreshable.hpp>
39 #include <swtypes.hxx>
41 using namespace ::ooo::vba
;
42 using namespace ::com::sun::star
;
44 // *** SwVbaField ***********************************************
46 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
)
48 mxTextField
.set( xTextField
, uno::UNO_QUERY_THROW
);
53 SwVbaField::getServiceImplName()
55 static rtl::OUString
sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaField") );
59 uno::Sequence
<rtl::OUString
>
60 SwVbaField::getServiceNames()
62 static uno::Sequence
< rtl::OUString
> aServiceNames
;
63 if ( aServiceNames
.getLength() == 0 )
65 aServiceNames
.realloc( 1 );
66 aServiceNames
[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.Field" ) );
71 // *** _ReadFieldParams ***********************************************
72 // the codes are copied from ww8par5.cxx
73 class _ReadFieldParams
77 xub_StrLen nLen
, nFnd
, nNext
, nSavPtr
;
80 _ReadFieldParams( const String
& rData
);
83 xub_StrLen
GoToTokenParam();
84 long SkipToNextToken();
85 xub_StrLen
GetTokenSttPtr() const { return nFnd
; }
87 xub_StrLen
FindNextStringPiece( xub_StrLen _nStart
= STRING_NOTFOUND
);
88 bool GetTokenSttFromTo(xub_StrLen
* _pFrom
, xub_StrLen
* _pTo
,
91 String
GetResult() const;
92 String
GetFieldName()const { return aFieldName
; }
96 _ReadFieldParams::_ReadFieldParams( const String
& _rData
)
97 : aData( _rData
), nLen( _rData
.Len() ), nNext( 0 )
100 erstmal nach einer oeffnenden Klammer oder einer Leerstelle oder einem
101 Anfuehrungszeichen oder einem Backslash suchen, damit der Feldbefehl
102 (also INCLUDEPICTURE bzw EINFUeGENGRAFIK bzw ...) ueberlesen wird
104 while( (nLen
> nNext
) && (aData
.GetChar( nNext
) == ' ') )
109 && (c
= aData
.GetChar( nNext
)) != ' '
118 aFieldName
= aData
.Copy( 0, nFnd
);
119 // cLastChar = aData.GetChar( nSavPtr );
123 _ReadFieldParams::~_ReadFieldParams()
125 // aData.SetChar( nSavPtr, cLastChar );
129 String
_ReadFieldParams::GetResult() const
131 return (STRING_NOTFOUND
== nFnd
)
133 : aData
.Copy( nFnd
, (nSavPtr
- nFnd
) );
137 xub_StrLen
_ReadFieldParams::GoToTokenParam()
139 xub_StrLen nOld
= nNext
;
140 if( -2 == SkipToNextToken() )
141 return GetTokenSttPtr();
143 return STRING_NOTFOUND
;
146 // ret: -2: NOT a '\' parameter but normal Text
147 long _ReadFieldParams::SkipToNextToken()
149 long nRet
= -1; // Ende
151 (STRING_NOTFOUND
!= nNext
) && (nLen
> nNext
) &&
152 STRING_NOTFOUND
!= (nFnd
= FindNextStringPiece(nNext
))
157 if ('\\' == aData
.GetChar(nFnd
) && '\\' != aData
.GetChar(nFnd
+ 1))
159 nRet
= aData
.GetChar(++nFnd
);
160 nNext
= ++nFnd
; // und dahinter setzen
166 (STRING_NOTFOUND
!= nSavPtr
) &&
168 ('"' == aData
.GetChar(nSavPtr
- 1)) ||
169 (0x201d == aData
.GetChar(nSavPtr
- 1))
180 // FindNextPara sucht naechsten Backslash-Parameter oder naechste Zeichenkette
181 // bis zum Blank oder naechsten "\" oder zum schliessenden Anfuehrungszeichen
182 // oder zum String-Ende von pStr.
184 // Ausgabe ppNext (falls ppNext != 0) Suchbeginn fuer naechsten Parameter bzw. 0
186 // Returnwert: 0 falls String-Ende erreicht,
187 // ansonsten Anfang des Paramters bzw. der Zeichenkette
189 xub_StrLen
_ReadFieldParams::FindNextStringPiece(const xub_StrLen nStart
)
191 xub_StrLen n
= ( STRING_NOTFOUND
== nStart
) ? nFnd
: nStart
; // Anfang
192 xub_StrLen n2
; // Ende
194 nNext
= STRING_NOTFOUND
; // Default fuer nicht gefunden
196 while( (nLen
> n
) && (aData
.GetChar( n
) == ' ') )
200 return STRING_NOTFOUND
; // String End reached!
202 if( (aData
.GetChar( n
) == '"') // Anfuehrungszeichen vor Para?
203 || (aData
.GetChar( n
) == 0x201c)
204 || (aData
.GetChar( n
) == 132) )
206 n
++; // Anfuehrungszeichen ueberlesen
207 n2
= n
; // ab hier nach Ende suchen
209 && (aData
.GetChar( n2
) != '"')
210 && (aData
.GetChar( n2
) != 0x201d)
211 && (aData
.GetChar( n2
) != 147) )
212 n2
++; // Ende d. Paras suchen
214 else // keine Anfuehrungszeichen
216 n2
= n
; // ab hier nach Ende suchen
217 while( (nLen
> n2
) && (aData
.GetChar( n2
) != ' ') ) // Ende d. Paras suchen
219 if( aData
.GetChar( n2
) == '\\' )
221 if( aData
.GetChar( n2
+1 ) == '\\' )
222 n2
+= 2; // Doppel-Backslash -> OK
227 break; // einfach-Backslash -> Ende
231 n2
++; // kein Backslash -> OK
236 if(aData
.GetChar( n2
) != ' ') n2
++;
244 // read parameters "1-3" or 1-3 with both values between 1 and nMax
245 bool _ReadFieldParams::GetTokenSttFromTo(USHORT
* pFrom
, USHORT
* pTo
, USHORT nMax
)
249 xub_StrLen n
= GoToTokenParam();
250 if( STRING_NOTFOUND
!= n
)
253 String
sParams( GetResult() );
255 xub_StrLen nIndex
= 0;
256 String
sStart( sParams
.GetToken(0, '-', nIndex
) );
257 if( STRING_NOTFOUND
!= nIndex
)
259 nStart
= static_cast<USHORT
>(sStart
.ToInt32());
260 nEnd
= static_cast<USHORT
>(sParams
.Copy(nIndex
).ToInt32());
263 if( pFrom
) *pFrom
= nStart
;
264 if( pTo
) *pTo
= nEnd
;
266 return nStart
&& nEnd
&& (nMax
>= nStart
) && (nMax
>= nEnd
);
269 // *** SwVbaFields ***********************************************
271 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
)
273 uno::Reference
< text::XTextField
> xTextField( aSource
, uno::UNO_QUERY_THROW
);
274 uno::Reference
< text::XTextDocument
> xTextDocument( xModel
, uno::UNO_QUERY_THROW
);
275 uno::Reference
< word::XField
> xField( new SwVbaField( xParent
, xContext
, xTextDocument
, xTextField
) );
276 return uno::makeAny( xField
);
279 typedef ::cppu::WeakImplHelper1
< css::container::XEnumeration
> FieldEnumeration_BASE
;
280 typedef ::cppu::WeakImplHelper2
< container::XIndexAccess
, container::XEnumerationAccess
> FieldCollectionHelper_BASE
;
282 class FieldEnumeration
: public FieldEnumeration_BASE
284 uno::Reference
< XHelperInterface
> mxParent
;
285 uno::Reference
< uno::XComponentContext
> mxContext
;
286 uno::Reference
< frame::XModel
> mxModel
;
287 uno::Reference
< container::XEnumeration
> mxEnumeration
;
289 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
)
292 virtual ::sal_Bool SAL_CALL
hasMoreElements( ) throw (uno::RuntimeException
)
294 return mxEnumeration
->hasMoreElements();
296 virtual uno::Any SAL_CALL
nextElement( ) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
298 if ( !hasMoreElements() )
299 throw container::NoSuchElementException();
300 return lcl_createField( mxParent
, mxContext
, mxModel
, mxEnumeration
->nextElement() );
304 class FieldCollectionHelper
: public FieldCollectionHelper_BASE
306 uno::Reference
< XHelperInterface
> mxParent
;
307 uno::Reference
< uno::XComponentContext
> mxContext
;
308 uno::Reference
< frame::XModel
> mxModel
;
309 uno::Reference
< container::XEnumerationAccess
> mxEnumerationAccess
;
311 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
)
313 uno::Reference
< text::XTextFieldsSupplier
> xSupp( xModel
, uno::UNO_QUERY_THROW
);
314 mxEnumerationAccess
.set( xSupp
->getTextFields(), uno::UNO_QUERY_THROW
);
317 virtual uno::Type SAL_CALL
getElementType( ) throw (uno::RuntimeException
) { return mxEnumerationAccess
->getElementType(); }
318 virtual ::sal_Bool SAL_CALL
hasElements( ) throw (uno::RuntimeException
) { return mxEnumerationAccess
->hasElements(); }
320 virtual ::sal_Int32 SAL_CALL
getCount( ) throw (uno::RuntimeException
)
322 uno::Reference
< container::XEnumeration
> xEnumeration
= mxEnumerationAccess
->createEnumeration();
323 sal_Int32 nCount
= 0;
324 while( xEnumeration
->hasMoreElements() )
327 xEnumeration
->nextElement();
331 virtual uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) throw (lang::IndexOutOfBoundsException
, lang::WrappedTargetException
, uno::RuntimeException
)
333 if( Index
< 0 || Index
>= getCount() )
334 throw lang::IndexOutOfBoundsException();
336 uno::Reference
< container::XEnumeration
> xEnumeration
= mxEnumerationAccess
->createEnumeration();
337 sal_Int32 nCount
= 0;
338 while( xEnumeration
->hasMoreElements() )
340 if( nCount
== Index
)
342 return xEnumeration
->nextElement();
346 throw lang::IndexOutOfBoundsException();
348 // XEnumerationAccess
349 virtual uno::Reference
< container::XEnumeration
> SAL_CALL
createEnumeration( ) throw (uno::RuntimeException
)
351 uno::Reference
< container::XEnumeration
> xEnumeration
= mxEnumerationAccess
->createEnumeration();
352 return uno::Reference
< container::XEnumeration
>( new FieldEnumeration( mxParent
, mxContext
, mxModel
, xEnumeration
) );
356 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
)
358 mxMSF
.set( mxModel
, uno::UNO_QUERY_THROW
);
361 uno::Reference
< word::XField
> SAL_CALL
362 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
)
364 sal_Int32 nType
= word::WdFieldType::wdFieldEmpty
;
370 if( ( nType
== word::WdFieldType::wdFieldEmpty
) && ( sText
.getLength() > 0 ) )
372 _ReadFieldParams
aReadParam(sText
);
373 sFieldName
= aReadParam
.GetFieldName();
376 uno::Reference
< text::XTextContent
> xTextField
;
377 if( nType
== word::WdFieldType::wdFieldFileName
|| sFieldName
.EqualsIgnoreCaseAscii("FILENAME") )
379 xTextField
.set( Create_Field_FileName( sText
), uno::UNO_QUERY_THROW
);
383 throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference
< uno::XInterface
>() );
386 SwVbaRange
* pVbaRange
= dynamic_cast< SwVbaRange
* >( Range
.get() );
387 uno::Reference
< text::XTextRange
> xTextRange
= pVbaRange
->getXTextRange();
388 uno::Reference
< text::XText
> xText
= xTextRange
->getText();
389 xText
->insertTextContent( xTextRange
, xTextField
, true );
390 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
) ) );
393 uno::Reference
< text::XTextField
> SwVbaFields::Create_Field_FileName( const rtl::OUString _text
) throw (uno::RuntimeException
)
395 uno::Reference
< text::XTextField
> xTextField( mxMSF
->createInstance( rtl::OUString::createFromAscii("com.sun.star.text.TextField.FileName") ), uno::UNO_QUERY_THROW
);
396 sal_Int16 nFileFormat
= text::FilenameDisplayFormat::NAME_AND_EXT
;
397 if( _text
.getLength() > 0 )
400 _ReadFieldParams
aReadParam( _text
);
401 while (-1 != (nRet
= aReadParam
.SkipToNextToken()))
406 nFileFormat
= text::FilenameDisplayFormat::FULL
;
409 //Skip over MERGEFORMAT
410 aReadParam
.SkipToNextToken();
413 DebugHelper::exception(SbERR_BAD_ARGUMENT
, rtl::OUString());
419 uno::Reference
< beans::XPropertySet
> xProps( xTextField
, uno::UNO_QUERY_THROW
);
420 xProps
->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FileFormat") ), uno::makeAny( nFileFormat
) );
425 uno::Reference
< container::XEnumeration
> SAL_CALL
426 SwVbaFields::createEnumeration() throw (uno::RuntimeException
)
428 uno::Reference
< container::XEnumerationAccess
> xEnumerationAccess( m_xIndexAccess
, uno::UNO_QUERY_THROW
);
429 return xEnumerationAccess
->createEnumeration();
432 // ScVbaCollectionBaseImpl
434 SwVbaFields::createCollectionObject( const uno::Any
& aSource
)
436 return lcl_createField( mxParent
, mxContext
, mxModel
, aSource
);
439 sal_Int32 SAL_CALL
SwVbaFields::Update() throw (uno::RuntimeException
)
441 sal_Int32 nUpdate
= 1;
444 uno::Reference
< text::XTextFieldsSupplier
> xSupp( mxModel
, uno::UNO_QUERY_THROW
);
445 uno::Reference
< util::XRefreshable
> xRef( xSupp
->getTextFields(), uno::UNO_QUERY_THROW
);
448 }catch( uno::Exception
)
457 SwVbaFields::getServiceImplName()
459 static rtl::OUString
sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaFields") );
463 // XEnumerationAccess
465 SwVbaFields::getElementType() throw (uno::RuntimeException
)
467 return word::XField::static_type(0);
470 uno::Sequence
<rtl::OUString
>
471 SwVbaFields::getServiceNames()
473 static uno::Sequence
< rtl::OUString
> aServiceNames
;
474 if ( aServiceNames
.getLength() == 0 )
476 aServiceNames
.realloc( 1 );
477 aServiceNames
[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.Fields" ) );
479 return aServiceNames
;