update dev300-m58
[ooovba.git] / sw / source / ui / vba / vbafield.cxx
blob6effe4d2aca9c415abfd9b25d27c8067e6ce55b1
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: $
10 * $Revision: $
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 );
51 // XHelperInterface
52 rtl::OUString&
53 SwVbaField::getServiceImplName()
55 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaField") );
56 return sImplName;
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" ) );
68 return aServiceNames;
71 // *** _ReadFieldParams ***********************************************
72 // the codes are copied from ww8par5.cxx
73 class _ReadFieldParams
75 private:
76 String aData;
77 xub_StrLen nLen, nFnd, nNext, nSavPtr;
78 String aFieldName;
79 public:
80 _ReadFieldParams( const String& rData );
81 ~_ReadFieldParams();
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,
89 xub_StrLen _nMax);
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 ) == ' ') )
105 ++nNext;
107 sal_Unicode c;
108 while( nLen > nNext
109 && (c = aData.GetChar( nNext )) != ' '
110 && c != '"'
111 && c != '\\'
112 && c != 132
113 && c != 0x201c )
114 ++nNext;
116 nFnd = nNext;
117 nSavPtr = 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)
132 ? aEmptyStr
133 : aData.Copy( nFnd, (nSavPtr - nFnd) );
137 xub_StrLen _ReadFieldParams::GoToTokenParam()
139 xub_StrLen nOld = nNext;
140 if( -2 == SkipToNextToken() )
141 return GetTokenSttPtr();
142 nNext = nOld;
143 return STRING_NOTFOUND;
146 // ret: -2: NOT a '\' parameter but normal Text
147 long _ReadFieldParams::SkipToNextToken()
149 long nRet = -1; // Ende
150 if (
151 (STRING_NOTFOUND != nNext) && (nLen > nNext) &&
152 STRING_NOTFOUND != (nFnd = FindNextStringPiece(nNext))
155 nSavPtr = nNext;
157 if ('\\' == aData.GetChar(nFnd) && '\\' != aData.GetChar(nFnd + 1))
159 nRet = aData.GetChar(++nFnd);
160 nNext = ++nFnd; // und dahinter setzen
162 else
164 nRet = -2;
165 if (
166 (STRING_NOTFOUND != nSavPtr ) &&
168 ('"' == aData.GetChar(nSavPtr - 1)) ||
169 (0x201d == aData.GetChar(nSavPtr - 1))
173 --nSavPtr;
177 return nRet;
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 ) == ' ') )
197 ++n;
199 if( nLen == 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
208 while( (nLen > n2)
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
223 else
225 if( n2 > n )
226 n2--;
227 break; // einfach-Backslash -> Ende
230 else
231 n2++; // kein Backslash -> OK
234 if( nLen > n2 )
236 if(aData.GetChar( n2 ) != ' ') n2++;
237 nNext = n2;
239 return n;
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)
247 USHORT nStart = 0;
248 USHORT nEnd = 0;
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;
288 public:
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;
310 public:
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 );
316 // XElementAccess
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(); }
319 // XIndexAccess
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() )
326 ++nCount;
327 xEnumeration->nextElement();
329 return nCount;
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();
344 ++nCount;
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;
365 Type >>= nType;
366 rtl::OUString sText;
367 Text >>= sText;
369 String sFieldName;
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 );
381 else
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 )
399 long nRet;
400 _ReadFieldParams aReadParam( _text );
401 while (-1 != (nRet = aReadParam.SkipToNextToken()))
403 switch (nRet)
405 case 'p':
406 nFileFormat = text::FilenameDisplayFormat::FULL;
407 break;
408 case '*':
409 //Skip over MERGEFORMAT
410 aReadParam.SkipToNextToken();
411 break;
412 default:
413 DebugHelper::exception(SbERR_BAD_ARGUMENT, rtl::OUString());
414 break;
419 uno::Reference< beans::XPropertySet > xProps( xTextField, uno::UNO_QUERY_THROW );
420 xProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FileFormat") ), uno::makeAny( nFileFormat ) );
422 return xTextField;
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
433 uno::Any
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 );
446 xRef->refresh();
447 nUpdate = 0;
448 }catch( uno::Exception )
450 nUpdate = 1;
452 return nUpdate;
455 // XHelperInterface
456 rtl::OUString&
457 SwVbaFields::getServiceImplName()
459 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaFields") );
460 return sImplName;
463 // XEnumerationAccess
464 uno::Type SAL_CALL
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;