1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 
31 #include "elementimport.hxx"
32 #include "xmloff/xmlimp.hxx"
33 #include "xmloff/nmspmap.hxx"
34 #include "xmloff/xmluconv.hxx"
35 #include "strings.hxx"
36 #include "callbacks.hxx"
37 #include "attriblistmerge.hxx"
38 #include "xmloff/xmlnmspe.hxx"
39 #include "eventimport.hxx"
40 #include "xmloff/txtstyli.hxx"
41 #include "formenums.hxx"
42 #include "xmloff/xmltoken.hxx"
43 #include "gridcolumnproptranslator.hxx"
44 #include "property_description.hxx"
45 #include "property_meta_data.hxx"
46 
47 /** === begin UNO includes === **/
48 #include <com/sun/star/text/XText.hpp>
49 #include <com/sun/star/util/XCloneable.hpp>
50 #include <com/sun/star/form/FormComponentType.hpp>
51 #include <com/sun/star/awt/ImagePosition.hpp>
52 #include <com/sun/star/beans/XMultiPropertySet.hpp>
53 #include <com/sun/star/beans/XPropertyContainer.hpp>
54 #include <com/sun/star/beans/PropertyAttribute.hpp>
55 /** === end UNO includes === **/
56 
57 #include <tools/urlobj.hxx>
58 #include <tools/diagnose_ex.h>
59 #include <tools/time.hxx>
60 #include <rtl/logfile.hxx>
61 #include <comphelper/extract.hxx>
62 #include <comphelper/types.hxx>
63 
64 #include <algorithm>
65 #include <functional>
66 
67 //.........................................................................
68 namespace xmloff
69 {
70 //.........................................................................
71 
72     using namespace ::xmloff::token;
73 	using namespace ::com::sun::star;
74 	using namespace ::com::sun::star::uno;
75 	using namespace ::com::sun::star::awt;
76 	using namespace ::com::sun::star::container;
77 	using namespace ::com::sun::star::beans;
78 	using namespace ::com::sun::star::script;
79 	using namespace ::com::sun::star::lang;
80 	using namespace ::com::sun::star::form;
81 	using namespace ::com::sun::star::xml;
82 	using namespace ::com::sun::star::util;
83 	using namespace ::com::sun::star::text;
84     using namespace ::comphelper;
85 
86 #define PROPID_VALUE			1
87 #define PROPID_CURRENT_VALUE	2
88 #define PROPID_MIN_VALUE		3
89 #define PROPID_MAX_VALUE		4
90 
91 	//=====================================================================
92 	struct PropertyValueLess
93 	{
94 		sal_Bool operator()(const PropertyValue& _rLeft, const PropertyValue& _rRight)
95 		{
96 			return _rLeft.Name < _rRight.Name;
97 		}
98 	};
99 
100 	//=====================================================================
101 	struct PropertyValueCompare : public ::std::binary_function< PropertyValue, ::rtl::OUString, bool>
102 	{
103 		bool operator() (const PropertyValue& lhs, const ::rtl::OUString& rhs) const
104 		{
105 			return lhs.Name == rhs;
106 		}
107 		bool operator() (const ::rtl::OUString& lhs, const PropertyValue& rhs) const
108 		{
109 			return lhs == rhs.Name;
110 		}
111 	};
112 
113 	//=====================================================================
114 	template <class ELEMENT>
115 	void pushBackSequenceElement(Sequence< ELEMENT >& _rContainer, const ELEMENT& _rElement)
116 	{
117 		sal_Int32 nLen = _rContainer.getLength();
118 		_rContainer.realloc(nLen + 1);
119 		_rContainer[nLen] = _rElement;
120 	}
121 
122 	//=====================================================================
123 	//= OElementNameMap
124 	//=====================================================================
125 	//---------------------------------------------------------------------
126 	OElementNameMap::MapString2Element	OElementNameMap::s_sElementTranslations;
127 
128 	//---------------------------------------------------------------------
129 	const OControlElement::ElementType& operator ++(OControlElement::ElementType& _e)
130 	{
131 		OControlElement::ElementType e = _e;
132 		sal_Int32 nAsInt = static_cast<sal_Int32>(e);
133 		_e = static_cast<OControlElement::ElementType>( ++nAsInt );
134 		return _e;
135 	}
136 
137 	//---------------------------------------------------------------------
138 	OControlElement::ElementType OElementNameMap::getElementType(const ::rtl::OUString& _rName)
139 	{
140 		if ( s_sElementTranslations.empty() )
141 		{	// initialize
142 			for (ElementType eType=(ElementType)0; eType<UNKNOWN; ++eType)
143 				s_sElementTranslations[::rtl::OUString::createFromAscii(getElementName(eType))] = eType;
144 		}
145 		ConstMapString2ElementIterator aPos = s_sElementTranslations.find(_rName);
146 		if (s_sElementTranslations.end() != aPos)
147 			return aPos->second;
148 
149 		return UNKNOWN;
150 	}
151 
152 	//=====================================================================
153 	//= OElementImport
154 	//=====================================================================
155 	//---------------------------------------------------------------------
156 	OElementImport::OElementImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
157 			const Reference< XNameContainer >& _rxParentContainer)
158 		:OPropertyImport(_rImport, _nPrefix, _rName)
159 		,m_rFormImport(_rImport)
160 		,m_rEventManager(_rEventManager)
161 		,m_pStyleElement( NULL )
162         ,m_xParentContainer(_rxParentContainer)
163         ,m_bImplicitGenericAttributeHandling( true )
164 	{
165 		OSL_ENSURE(m_xParentContainer.is(), "OElementImport::OElementImport: invalid parent container!");
166 	}
167 
168     //---------------------------------------------------------------------
169     OElementImport::~OElementImport()
170     {
171     }
172 
173 	//---------------------------------------------------------------------
174     ::rtl::OUString OElementImport::determineDefaultServiceName() const
175     {
176         return ::rtl::OUString();
177     }
178 
179 	//---------------------------------------------------------------------
180 	void OElementImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
181 	{
182 		ENTER_LOG_CONTEXT( "xmloff::OElementImport - importing one element" );
183 
184         const SvXMLNamespaceMap& rMap = m_rContext.getGlobalContext().GetNamespaceMap();
185         const ::rtl::OUString sImplNameAttribute = rMap.GetQNameByKey( XML_NAMESPACE_FORM, GetXMLToken( XML_CONTROL_IMPLEMENTATION ) );
186         const ::rtl::OUString sControlImplementation = _rxAttrList->getValueByName( sImplNameAttribute );
187 
188         // retrieve the service name
189 		if ( sControlImplementation.getLength() > 0 )
190         {
191 		    ::rtl::OUString sOOoImplementationName;
192 		    const sal_uInt16 nImplPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sControlImplementation, &sOOoImplementationName );
193 		    m_sServiceName = ( nImplPrefix == XML_NAMESPACE_OOO ) ? sOOoImplementationName : sControlImplementation;
194         }
195 
196         if ( !m_sServiceName.getLength() )
197             determineDefaultServiceName();
198 
199         // create the object *now*. This allows setting properties in the various handleAttribute methods.
200         // (Though currently not all code is migrated to this pattern, most attributes are still handled
201         // by remembering the value (via implPushBackPropertyValue), and setting the correct property value
202         // later (in OControlImport::StartElement).)
203 		m_xElement = createElement();
204         if ( m_xElement.is() )
205             m_xInfo = m_xElement->getPropertySetInfo();
206 
207         // call the base class
208 		OPropertyImport::StartElement( _rxAttrList );
209 	}
210 
211 	//---------------------------------------------------------------------
212 	SvXMLImportContext* OElementImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
213 		const Reference< sax::XAttributeList >& _rxAttrList)
214 	{
215 		if( token::IsXMLToken(_rLocalName, token::XML_EVENT_LISTENERS) && (XML_NAMESPACE_OFFICE == _nPrefix))
216 			return new OFormEventsImportContext(m_rFormImport.getGlobalContext(), _nPrefix, _rLocalName, *this);
217 
218 		return OPropertyImport::CreateChildContext(_nPrefix, _rLocalName, _rxAttrList);
219 	}
220 
221 	//---------------------------------------------------------------------
222 	void OElementImport::EndElement()
223 	{
224 		OSL_ENSURE(m_xElement.is(), "OElementImport::EndElement: invalid element created!");
225 		if (!m_xElement.is())
226 			return;
227 
228         // apply the non-generic properties
229         implApplySpecificProperties();
230 
231 		// set the generic properties
232 		implApplyGenericProperties();
233 
234 		// set the style properties
235 		if ( m_pStyleElement && m_xElement.is() )
236 		{
237             Reference< XPropertySet > xPropTranslation =
238                 new OGridColumnPropertyTranslator( Reference< XMultiPropertySet >( m_xElement, UNO_QUERY ) );
239 			const_cast< XMLTextStyleContext* >( m_pStyleElement )->FillPropertySet( xPropTranslation );
240 
241 			const ::rtl::OUString sNumberStyleName = const_cast< XMLTextStyleContext* >( m_pStyleElement )->GetDataStyleName( );
242 			if ( sNumberStyleName.getLength() )
243 				// the style also has a number (sub) style
244 				m_rContext.applyControlNumberStyle( m_xElement, sNumberStyleName );
245 		}
246 
247 		// insert the element into the parent container
248 		if (!m_sName.getLength())
249 		{
250 			OSL_ENSURE(sal_False, "OElementImport::EndElement: did not find a name attribute!");
251 			m_sName = implGetDefaultName();
252 		}
253 
254 		m_xParentContainer->insertByName(m_sName, makeAny(m_xElement));
255 		LEAVE_LOG_CONTEXT( );
256 	}
257 
258 	//---------------------------------------------------------------------
259 	void OElementImport::implApplySpecificProperties()
260     {
261         if ( m_aValues.empty() )
262             return;
263 
264 		// set all the properties we collected
265 #if OSL_DEBUG_LEVEL > 0
266 		// check if the object has all the properties
267 		// (We do this in the non-pro version only. Doing it all the time would be much to expensive)
268 		if ( m_xInfo.is() )
269 		{
270             PropertyValueArray::const_iterator aEnd = m_aValues.end();
271 			for (	PropertyValueArray::iterator aCheck = m_aValues.begin();
272 					aCheck != aEnd;
273 					++aCheck
274 				)
275 			{
276 				OSL_ENSURE(m_xInfo->hasPropertyByName(aCheck->Name),
277 						::rtl::OString("OElementImport::implApplySpecificProperties: read a property (")
278 					+=	::rtl::OString(aCheck->Name.getStr(), aCheck->Name.getLength(), RTL_TEXTENCODING_ASCII_US)
279 					+=	::rtl::OString(") which does not exist on the element!"));
280 			}
281 		}
282 #endif
283 
284 		// set the properties
285 		const Reference< XMultiPropertySet > xMultiProps(m_xElement, UNO_QUERY);
286 		sal_Bool bSuccess = sal_False;
287 		if (xMultiProps.is())
288 		{
289 			// translate our properties so that the XMultiPropertySet can handle them
290 
291 			// sort our property value array so that we can use it in a setPropertyValues
292 			::std::sort( m_aValues.begin(), m_aValues.end(), PropertyValueLess());
293 
294 			// the names
295 			Sequence< ::rtl::OUString > aNames(m_aValues.size());
296 			::rtl::OUString* pNames = aNames.getArray();
297 			// the values
298 			Sequence< Any > aValues(m_aValues.size());
299 			Any* pValues = aValues.getArray();
300 			// copy
301 
302             PropertyValueArray::iterator aEnd = m_aValues.end();
303 			for	(	PropertyValueArray::iterator aPropValues = m_aValues.begin();
304 					aPropValues != aEnd;
305 					++aPropValues, ++pNames, ++pValues
306 				)
307 			{
308 				*pNames = aPropValues->Name;
309 				*pValues = aPropValues->Value;
310 			}
311 
312 			try
313 			{
314 				xMultiProps->setPropertyValues(aNames, aValues);
315 				bSuccess = sal_True;
316 			}
317 			catch(Exception&)
318 			{
319 				OSL_ENSURE(sal_False, "OElementImport::implApplySpecificProperties: could not set the properties (using the XMultiPropertySet)!");
320 			}
321 		}
322 
323 		if (!bSuccess)
324 		{	// no XMultiPropertySet or setting all properties at once failed
325             PropertyValueArray::iterator aEnd = m_aValues.end();
326 			for	(	PropertyValueArray::iterator aPropValues = m_aValues.begin();
327 					aPropValues != aEnd;
328 					++aPropValues
329 				)
330 			{
331 				// this try/catch here is expensive, but because this is just a fallback which should normally not be
332 				// used it's acceptable this way ...
333 				try
334 				{
335 					m_xElement->setPropertyValue(aPropValues->Name, aPropValues->Value);
336 				}
337 				catch(Exception&)
338 				{
339 					OSL_ENSURE(sal_False,
340 							::rtl::OString("OElementImport::implApplySpecificProperties: could not set the property \"")
341 						+=	::rtl::OString(aPropValues->Name.getStr(), aPropValues->Name.getLength(), RTL_TEXTENCODING_ASCII_US)
342 						+=	::rtl::OString("\"!"));
343 				}
344 			}
345 		}
346     }
347 
348 	//---------------------------------------------------------------------
349 	void OElementImport::implApplyGenericProperties()
350 	{
351         if ( m_aGenericValues.empty() )
352             return;
353 
354         Reference< XPropertyContainer > xDynamicProperties( m_xElement, UNO_QUERY );
355 
356         PropertyValueArray::iterator aEnd = m_aGenericValues.end();
357 		for (   PropertyValueArray::iterator aPropValues =
358 				m_aGenericValues.begin();
359 				aPropValues != aEnd;
360 				++aPropValues
361 			)
362 		{
363 			// check property type for numeric types before setting
364 			// the property
365 			try
366 			{
367                 // if such a property does not yet exist at the element, create it if necessary
368                 const bool bExistentProperty = m_xInfo->hasPropertyByName( aPropValues->Name );
369                 if ( !bExistentProperty )
370                 {
371                     if ( !xDynamicProperties.is() )
372                     {
373                     #if OSL_DEBUG_LEVEL > 0
374                         ::rtl::OString aMessage( "OElementImport::implApplyGenericProperties: encountered an unknown property (" );
375                         aMessage += ::rtl::OUStringToOString( aPropValues->Name, RTL_TEXTENCODING_ASCII_US );
376                         aMessage += "), but component is no PropertyBag!";
377                         OSL_ENSURE( false, aMessage.getStr() );
378                     #endif
379                         continue;
380                     }
381 
382                     xDynamicProperties->addProperty(
383                         aPropValues->Name,
384                         PropertyAttribute::BOUND | PropertyAttribute::REMOVEABLE,
385                         aPropValues->Value
386                     );
387 
388                     // re-fetch the PropertySetInfo
389                     m_xInfo = m_xElement->getPropertySetInfo();
390                 }
391 
392                 // determine the type of the value (source for the following conversion)
393 				TypeClass eValueTypeClass = aPropValues->Value.getValueTypeClass();
394 				const sal_Bool bValueIsSequence = TypeClass_SEQUENCE == eValueTypeClass;
395 				if ( bValueIsSequence )
396 				{
397                     uno::Type aSimpleType( getSequenceElementType( aPropValues->Value.getValueType() ) );
398 					eValueTypeClass = aSimpleType.getTypeClass();
399 				}
400 
401                 // determine the type of the property (target for the following conversion)
402                 const Property aProperty( m_xInfo->getPropertyByName( aPropValues->Name ) );
403 				TypeClass ePropTypeClass = aProperty.Type.getTypeClass();
404 				const sal_Bool bPropIsSequence = TypeClass_SEQUENCE == ePropTypeClass;
405 				if( bPropIsSequence )
406 				{
407                     uno::Type aSimpleType( ::comphelper::getSequenceElementType( aProperty.Type ) );
408 					ePropTypeClass = aSimpleType.getTypeClass();
409 				}
410 
411                 if ( bPropIsSequence != bValueIsSequence )
412                 {
413                     OSL_ENSURE( false, "OElementImport::implApplyGenericProperties: either both value and property should be a sequence, or none of them!" );
414                     continue;
415                 }
416 
417                 if ( bValueIsSequence )
418                 {
419                     OSL_ENSURE( eValueTypeClass == TypeClass_ANY,
420                         "OElementImport::implApplyGenericProperties: only ANYs should have been imported as generic list property!" );
421                         // (OPropertyImport should produce only Sequencer< Any >, since it cannot know the real type
422 
423                     OSL_ENSURE( ePropTypeClass == TypeClass_SHORT,
424                         "OElementImport::implApplyGenericProperties: conversion to sequences other than 'sequence< short >' not implemented, yet!" );
425 
426                     Sequence< Any > aXMLValueList;
427                     aPropValues->Value >>= aXMLValueList;
428                     Sequence< sal_Int16 > aPropertyValueList( aXMLValueList.getLength() );
429 
430                     const Any*       pXMLValue = aXMLValueList.getConstArray();
431                           sal_Int16* pPropValue = aPropertyValueList.getArray();
432 
433                     for ( sal_Int32 i=0; i<aXMLValueList.getLength(); ++i, ++pXMLValue, ++pPropValue )
434                     {
435                         // only value sequences of numeric types implemented so far.
436                         double nVal( 0 );
437                         OSL_VERIFY( *pXMLValue >>= nVal );
438                         *pPropValue = static_cast< sal_Int16 >( nVal );
439                     }
440 
441                     aPropValues->Value <<= aPropertyValueList;
442                 }
443                 else if ( ePropTypeClass != eValueTypeClass )
444 				{
445                     switch ( eValueTypeClass )
446                     {
447                     case TypeClass_DOUBLE:
448                     {
449 					    double nVal = 0;
450 					    aPropValues->Value >>= nVal;
451 					    switch( ePropTypeClass )
452 					    {
453 					    case TypeClass_BYTE:
454                             aPropValues->Value <<= static_cast< sal_Int8 >( nVal );
455                             break;
456 					    case TypeClass_SHORT:
457                             aPropValues->Value <<= static_cast< sal_Int16 >( nVal );
458 						    break;
459 					    case TypeClass_LONG:
460 					    case TypeClass_ENUM:
461                             aPropValues->Value <<= static_cast< sal_Int32 >( nVal );
462 						    break;
463 					    case TypeClass_HYPER:
464                             aPropValues->Value <<= static_cast< sal_Int64 >( nVal );
465 						    break;
466                         default:
467                             OSL_ENSURE( false, "OElementImport::implApplyGenericProperties: unsupported value type!" );
468                             break;
469 					    }
470                     }
471                     break;
472                     default:
473                         OSL_ENSURE( false, "OElementImport::implApplyGenericProperties: non-double values not supported!" );
474                         break;
475                     }
476 				}
477 
478                 m_xElement->setPropertyValue( aPropValues->Name, aPropValues->Value );
479 			}
480 			catch(Exception&)
481 			{
482 				OSL_ENSURE(sal_False,
483 						::rtl::OString("OElementImport::EndElement: could not set the property \"")
484 					+=	::rtl::OString(aPropValues->Name.getStr(), aPropValues->Name.getLength(), RTL_TEXTENCODING_ASCII_US)
485 					+=	::rtl::OString("\"!"));
486 			}
487 		}
488 	}
489 
490 	//---------------------------------------------------------------------
491 	::rtl::OUString OElementImport::implGetDefaultName() const
492 	{
493 		// no optimization here. If this method gets called, the XML stream did not contain a name for the
494 		// element, which is a heavy error. So in this case we don't care for performance
495 		Sequence< ::rtl::OUString > aNames = m_xParentContainer->getElementNames();
496 		static const ::rtl::OUString sUnnamedName = ::rtl::OUString::createFromAscii("unnamed");
497 
498 		::rtl::OUString sReturn;
499 		const ::rtl::OUString* pNames = NULL;
500 		const ::rtl::OUString* pNamesEnd = aNames.getConstArray() + aNames.getLength();
501 		for (sal_Int32 i=0; i<32768; ++i)	// the limit is nearly arbitrary ...
502 		{
503 			// assemble the new name (suggestion)
504 			sReturn = sUnnamedName;
505 			sReturn += ::rtl::OUString::valueOf(i);
506 			// check the existence (this is the bad performance part ....)
507 			for (pNames = aNames.getConstArray(); pNames<pNamesEnd; ++pNames)
508 			{
509 				if (*pNames == sReturn)
510 				{
511 					break;
512 				}
513 			}
514 			if (pNames<pNamesEnd)
515 				// found the name
516 				continue;
517 			return sReturn;
518 		}
519 		OSL_ENSURE(sal_False, "OElementImport::implGetDefaultName: did not find a free name!");
520 		return sUnnamedName;
521 	}
522 
523 	//---------------------------------------------------------------------
524     PropertyGroups::const_iterator OElementImport::impl_matchPropertyGroup( const PropertyGroups& i_propertyGroups ) const
525     {
526         ENSURE_OR_RETURN( m_xInfo.is(), "OElementImport::impl_matchPropertyGroup: no property set info!", i_propertyGroups.end() );
527 
528         for (   PropertyGroups::const_iterator group = i_propertyGroups.begin();
529                 group != i_propertyGroups.end();
530                 ++group
531             )
532         {
533             bool missingProp = false;
534             for (   PropertyDescriptionList::const_iterator prop = group->begin();
535                     prop != group->end();
536                     ++prop
537                 )
538             {
539                 if ( !m_xInfo->hasPropertyByName( (*prop)->propertyName ) )
540                 {
541                     missingProp = true;
542                     break;
543                 }
544             }
545 
546             if ( missingProp )
547                 // try next group
548                 continue;
549 
550             return group;
551         }
552 
553         return i_propertyGroups.end();
554     }
555 
556 	//---------------------------------------------------------------------
557     bool OElementImport::tryGenericAttribute( sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue )
558     {
559         // the generic approach (which I hope all props will be migrated to, on the medium term): property handlers
560         const AttributeDescription attribute( metadata::getAttributeDescription( _nNamespaceKey, _rLocalName ) );
561         if ( attribute.attributeToken != XML_TOKEN_INVALID )
562         {
563             PropertyGroups propertyGroups;
564             metadata::getPropertyGroupList( attribute, propertyGroups );
565             const PropertyGroups::const_iterator pos = impl_matchPropertyGroup( propertyGroups );
566             if ( pos == propertyGroups.end() )
567                 return false;
568 
569             do
570             {
571                 const PropertyDescriptionList& rProperties( *pos );
572                 const PropertyDescription* first = *rProperties.begin();
573                 ENSURE_OR_BREAK( first != NULL, "OElementImport::handleAttribute: invalid property description!" );
574                 const PPropertyHandler handler = (*first->factory)( first->propertyId );
575                 ENSURE_OR_BREAK( handler.get() != NULL, "OElementImport::handleAttribute: invalid property handler!" );
576 
577                 PropertyValues aValues;
578                 for (   PropertyDescriptionList::const_iterator propDesc = rProperties.begin();
579                         propDesc != rProperties.end();
580                         ++propDesc
581                     )
582                 {
583                     aValues[ (*propDesc)->propertyId ] = Any();
584                 }
585                 if ( handler->getPropertyValues( _rValue, aValues ) )
586                 {
587                     for (   PropertyDescriptionList::const_iterator propDesc = rProperties.begin();
588                             propDesc != rProperties.end();
589                             ++propDesc
590                         )
591                     {
592                         implPushBackPropertyValue( (*propDesc)->propertyName, aValues[ (*propDesc)->propertyId ] );
593                     }
594                 }
595             }
596             while ( false );
597 
598             // handled
599             return true;
600         }
601         return false;
602     }
603 
604 	//---------------------------------------------------------------------
605 	bool OElementImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
606 	{
607 		if ( token::IsXMLToken( _rLocalName, token::XML_CONTROL_IMPLEMENTATION ) )
608             // ignore this, it has already been handled in OElementImport::StartElement
609             return true;
610 
611 		if ( token::IsXMLToken( _rLocalName, token::XML_NAME ) )
612         {
613             if ( !m_sName.getLength() )
614 			    // remember the name for later use in EndElement
615 				m_sName = _rValue;
616             return true;
617         }
618 
619 		// maybe it's the style attribute?
620 		if ( token::IsXMLToken( _rLocalName, token::XML_TEXT_STYLE_NAME ) )
621 		{
622 			const SvXMLStyleContext* pStyleContext = m_rContext.getStyleElement( _rValue );
623 			OSL_ENSURE( pStyleContext, "OElementImport::handleAttribute: do not know the style!" );
624 			// remember the element for later usage.
625 			m_pStyleElement = PTR_CAST( XMLTextStyleContext, pStyleContext );
626             return true;
627 		}
628 
629         if ( m_bImplicitGenericAttributeHandling )
630             if ( tryGenericAttribute( _nNamespaceKey, _rLocalName, _rValue ) )
631                 return true;
632 
633 		// let the base class handle it
634 		return OPropertyImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue);
635 	}
636 
637 	//---------------------------------------------------------------------
638 	Reference< XPropertySet > OElementImport::createElement()
639 	{
640 		Reference< XPropertySet > xReturn;
641 		if (m_sServiceName.getLength())
642 		{
643 			Reference< XInterface > xPure = m_rFormImport.getGlobalContext().getServiceFactory()->createInstance(m_sServiceName);
644 			OSL_ENSURE(xPure.is(),
645 						::rtl::OString("OElementImport::createElement: service factory gave me no object (service name: ")
646 					+=	::rtl::OString(m_sServiceName.getStr(), m_sServiceName.getLength(), RTL_TEXTENCODING_ASCII_US)
647 					+=	::rtl::OString(")!"));
648 			xReturn = Reference< XPropertySet >(xPure, UNO_QUERY);
649 		}
650 		else
651 			OSL_ENSURE(sal_False, "OElementImport::createElement: no service name to create an element!");
652 
653 		return xReturn;
654 	}
655 
656 	//---------------------------------------------------------------------
657 	void OElementImport::registerEvents(const Sequence< ScriptEventDescriptor >& _rEvents)
658 	{
659 		OSL_ENSURE(m_xElement.is(), "OElementImport::registerEvents: no element to register events for!");
660 		m_rEventManager.registerEvents(m_xElement, _rEvents);
661 	}
662 
663 	//---------------------------------------------------------------------
664 	void OElementImport::simulateDefaultedAttribute(const sal_Char* _pAttributeName, const ::rtl::OUString& _rPropertyName, const sal_Char* _pAttributeDefault)
665 	{
666 		OSL_ENSURE( m_xInfo.is(), "OPropertyImport::simulateDefaultedAttribute: the component should be more gossipy about it's properties!" );
667 
668 		if ( !m_xInfo.is() || m_xInfo->hasPropertyByName( _rPropertyName ) )
669 		{
670 			::rtl::OUString sLocalAttrName = ::rtl::OUString::createFromAscii(_pAttributeName);
671 			if ( !encounteredAttribute( sLocalAttrName ) )
672 				OSL_VERIFY( handleAttribute( XML_NAMESPACE_FORM, sLocalAttrName, ::rtl::OUString::createFromAscii( _pAttributeDefault ) ) );
673 		}
674 	}
675 
676 	//=====================================================================
677 	//= OControlImport
678 	//=====================================================================
679 	//---------------------------------------------------------------------
680 	OControlImport::OControlImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
681 			const Reference< XNameContainer >& _rxParentContainer)
682 		:OElementImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer)
683 		,m_eElementType(OControlElement::UNKNOWN)
684 	{
685         disableImplicitGenericAttributeHandling();
686 	}
687 
688 	//---------------------------------------------------------------------
689 	OControlImport::OControlImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
690 			const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType)
691 		:OElementImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer)
692 		,m_eElementType(_eType)
693 	{
694         disableImplicitGenericAttributeHandling();
695 	}
696 
697 	//---------------------------------------------------------------------
698     ::rtl::OUString OControlImport::determineDefaultServiceName() const
699     {
700         const sal_Char* pServiceName = NULL;
701         switch ( m_eElementType )
702         {
703         case OControlElement::TEXT:
704         case OControlElement::TEXT_AREA:
705         case OControlElement::PASSWORD:          pServiceName = "com.sun.star.form.component.TextField"; break;
706         case OControlElement::FILE:              pServiceName = "com.sun.star.form.component.FileControl"; break;
707         case OControlElement::FORMATTED_TEXT:    pServiceName = "com.sun.star.form.component.FormattedField"; break;
708         case OControlElement::FIXED_TEXT:        pServiceName = "com.sun.star.form.component.FixedText"; break;
709         case OControlElement::COMBOBOX:          pServiceName = "com.sun.star.form.component.ComboBox"; break;
710         case OControlElement::LISTBOX:           pServiceName = "com.sun.star.form.component.ListBox"; break;
711         case OControlElement::BUTTON:            pServiceName = "com.sun.star.form.component.CommandButton"; break;
712         case OControlElement::IMAGE:             pServiceName = "com.sun.star.form.component.ImageButton"; break;
713         case OControlElement::CHECKBOX:          pServiceName = "com.sun.star.form.component.CheckBox"; break;
714         case OControlElement::RADIO:             pServiceName = "com.sun.star.form.component.RadioButton"; break;
715         case OControlElement::FRAME:             pServiceName = "com.sun.star.form.component.GroupBox"; break;
716         case OControlElement::IMAGE_FRAME:       pServiceName = "com.sun.star.form.component.DatabaseImageControl"; break;
717         case OControlElement::HIDDEN:            pServiceName = "com.sun.star.form.component.HiddenControl"; break;
718         case OControlElement::GRID:              pServiceName = "com.sun.star.form.component.GridControl"; break;
719         case OControlElement::TIME:              pServiceName = "com.sun.star.form.component.DateField"; break;
720         case OControlElement::DATE:              pServiceName = "com.sun.star.form.component.TimeField"; break;
721         default:                                 break;
722         }
723         if ( pServiceName != NULL )
724             return ::rtl::OUString::createFromAscii( pServiceName );
725         return ::rtl::OUString();
726     }
727 
728 	//---------------------------------------------------------------------
729 	void OControlImport::addOuterAttributes(const Reference< sax::XAttributeList >& _rxOuterAttribs)
730 	{
731 		OSL_ENSURE(!m_xOuterAttributes.is(), "OControlImport::addOuterAttributes: already have these attributes!");
732 		m_xOuterAttributes = _rxOuterAttribs;
733 	}
734 
735 	//---------------------------------------------------------------------
736 	bool OControlImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
737 	{
738 		static const sal_Char* pLinkedCellAttributeName = OAttributeMetaData::getBindingAttributeName(BA_LINKED_CELL);
739 
740         if (IsXMLToken(_rLocalName, XML_ID))
741         {   // it's the control id
742             if (XML_NAMESPACE_XML == _nNamespaceKey)
743             {
744                 m_sControlId = _rValue;
745             }
746             else if (XML_NAMESPACE_FORM == _nNamespaceKey)
747             {
748                 if (!m_sControlId.getLength())
749                 {
750                     m_sControlId = _rValue;
751                 }
752             }
753             return true;
754         }
755 
756         if ( _rLocalName.equalsAscii( pLinkedCellAttributeName ) )
757         {   // it's the address of a spreadsheet cell
758             m_sBoundCellAddress = _rValue;
759             return true;
760         }
761 
762         if ( _nNamespaceKey == XML_NAMESPACE_XFORMS && IsXMLToken( _rLocalName, XML_BIND ) )
763         {
764             m_sBindingID = _rValue;
765             return true;
766         }
767 
768         if ( _nNamespaceKey == XML_NAMESPACE_FORM && IsXMLToken( _rLocalName, XML_XFORMS_LIST_SOURCE )  )
769         {
770             m_sListBindingID = _rValue;
771             return true;
772         }
773 
774         if  (   (   ( _nNamespaceKey == XML_NAMESPACE_FORM )
775                 &&  IsXMLToken( _rLocalName, XML_XFORMS_SUBMISSION )
776                 )
777             ||  (   ( _nNamespaceKey == XML_NAMESPACE_XFORMS )
778                 &&  IsXMLToken( _rLocalName, XML_SUBMISSION )
779                 )
780             )
781         {
782             m_sSubmissionID = _rValue;
783             return true;
784         }
785 
786         if ( OElementImport::tryGenericAttribute( _nNamespaceKey, _rLocalName, _rValue ) )
787             return true;
788 
789 		static const sal_Char* pValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_VALUE);
790 		static const sal_Char* pCurrentValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_VALUE);
791         static const sal_Char* pMinValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCA_MIN_VALUE);
792 		static const sal_Char* pMaxValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCA_MAX_VALUE);
793         static const sal_Char* pRepeatDelayAttributeName = OAttributeMetaData::getSpecialAttributeName( SCA_REPEAT_DELAY );
794 
795 		sal_Int32 nHandle = -1;
796         if ( _rLocalName.equalsAscii( pValueAttributeName ) )
797             nHandle = PROPID_VALUE;
798         else if ( _rLocalName.equalsAscii( pCurrentValueAttributeName ) )
799             nHandle = PROPID_CURRENT_VALUE;
800         else if ( _rLocalName.equalsAscii( pMinValueAttributeName ) )
801             nHandle = PROPID_MIN_VALUE;
802         else if ( _rLocalName.equalsAscii( pMaxValueAttributeName ) )
803             nHandle = PROPID_MAX_VALUE;
804         if ( nHandle != -1 )
805 		{
806 			// for the moment, simply remember the name and the value
807 			PropertyValue aProp;
808 			aProp.Name = _rLocalName;
809 			aProp.Handle = nHandle;
810 			aProp.Value <<= _rValue;
811 			m_aValueProperties.push_back(aProp);
812             return true;
813 		}
814 
815 		if ( _rLocalName.equalsAscii( pRepeatDelayAttributeName ) )
816         {
817             ::Time aTime;
818             sal_Int32 nFractions = 0;
819             if ( SvXMLUnitConverter::convertTimeDuration( _rValue, aTime, &nFractions ) )
820             {
821 			    PropertyValue aProp;
822 			    aProp.Name = PROPERTY_REPEAT_DELAY;
823 			    aProp.Value <<= (sal_Int32)( ( ( aTime.GetMSFromTime() / 1000 ) * 1000 ) + nFractions );
824 
825 			    implPushBackPropertyValue(aProp);
826             }
827             return true;
828         }
829 
830 		return OElementImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue );
831 	}
832 
833 	//---------------------------------------------------------------------
834 	void OControlImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
835 	{
836 		::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > xAttributes;
837 		if( m_xOuterAttributes.is() )
838 		{
839 			// merge the attribute lists
840 			OAttribListMerger* pMerger = new OAttribListMerger;
841 			// our own one
842 			pMerger->addList(_rxAttrList);
843 			// and the ones of our enclosing element
844 			pMerger->addList(m_xOuterAttributes);
845 			xAttributes = pMerger;
846 		}
847 		else
848 		{
849 			xAttributes = _rxAttrList;
850 		}
851 
852 		// let the base class handle all the attributes
853 		OElementImport::StartElement(xAttributes);
854 
855 		if ( !m_aValueProperties.empty() && m_xElement.is())
856 		{
857 			// get the property set info
858 			if (!m_xInfo.is())
859 			{
860 				OSL_ENSURE(sal_False, "OControlImport::StartElement: no PropertySetInfo!");
861 				return;
862 			}
863 
864 			const sal_Char* pValueProperty = NULL;
865 			const sal_Char* pCurrentValueProperty = NULL;
866 			const sal_Char* pMinValueProperty = NULL;
867 			const sal_Char* pMaxValueProperty = NULL;
868 
869 			sal_Bool bRetrievedValues = sal_False;
870 			sal_Bool bRetrievedValueLimits = sal_False;
871 
872 			// get the class id of our element
873 			sal_Int16 nClassId = FormComponentType::CONTROL;
874 			m_xElement->getPropertyValue(PROPERTY_CLASSID) >>= nClassId;
875 
876 			// translate the value properties we collected in handleAttributes
877             PropertyValueArray::iterator aEnd = m_aValueProperties.end();
878             for	(	PropertyValueArray::iterator aValueProps = m_aValueProperties.begin();
879 					aValueProps != aEnd;
880 					++aValueProps
881 				)
882 			{
883                 bool bSuccess = false;
884 				switch (aValueProps->Handle)
885 				{
886 					case PROPID_VALUE:
887 					case PROPID_CURRENT_VALUE:
888 					{
889 						// get the property names
890 						if (!bRetrievedValues)
891 						{
892 							getValuePropertyNames(m_eElementType, nClassId, pCurrentValueProperty, pValueProperty);
893                             ENSURE_OR_BREAK( pValueProperty, "OControlImport::StartElement: illegal value property names!" );
894 							bRetrievedValues = sal_True;
895 						}
896 						ENSURE_OR_BREAK((PROPID_VALUE != aValueProps->Handle) || pValueProperty,
897 							"OControlImport::StartElement: the control does not have a value property!");
898 						ENSURE_OR_BREAK((PROPID_CURRENT_VALUE != aValueProps->Handle) || pCurrentValueProperty,
899 							"OControlImport::StartElement: the control does not have a current-value property!");
900 
901 						// transfer the name
902 						if (PROPID_VALUE == aValueProps->Handle)
903 							aValueProps->Name = ::rtl::OUString::createFromAscii(pValueProperty);
904 						else
905 							aValueProps->Name = ::rtl::OUString::createFromAscii(pCurrentValueProperty);
906                         bSuccess = true;
907 					}
908 					break;
909 					case PROPID_MIN_VALUE:
910 					case PROPID_MAX_VALUE:
911 					{
912 						// get the property names
913 						if (!bRetrievedValueLimits)
914 						{
915 							getValueLimitPropertyNames(nClassId, pMinValueProperty, pMaxValueProperty);
916                             ENSURE_OR_BREAK( pMinValueProperty && pMaxValueProperty, "OControlImport::StartElement: illegal value limit property names!" );
917 							bRetrievedValueLimits = sal_True;
918 						}
919 						OSL_ENSURE((PROPID_MIN_VALUE != aValueProps->Handle) || pMinValueProperty,
920 							"OControlImport::StartElement: the control does not have a value property!");
921 						OSL_ENSURE((PROPID_MAX_VALUE != aValueProps->Handle) || pMaxValueProperty,
922 							"OControlImport::StartElement: the control does not have a current-value property!");
923 
924 						// transfer the name
925 						if (PROPID_MIN_VALUE == aValueProps->Handle)
926 							aValueProps->Name = ::rtl::OUString::createFromAscii(pMinValueProperty);
927 						else
928 							aValueProps->Name = ::rtl::OUString::createFromAscii(pMaxValueProperty);
929                         bSuccess = true;
930 					}
931 					break;
932 				}
933 
934                 if ( !bSuccess )
935                     continue;
936 
937 				// translate the value
938 				implTranslateValueProperty(m_xInfo, *aValueProps);
939 				// add the property to the base class' array
940 				implPushBackPropertyValue(*aValueProps);
941 			}
942 		}
943 	}
944 
945 	//---------------------------------------------------------------------
946 	void OControlImport::implTranslateValueProperty(const Reference< XPropertySetInfo >& _rxPropInfo,
947 		PropertyValue& _rPropValue)
948 	{
949 		OSL_ENSURE(_rxPropInfo->hasPropertyByName(_rPropValue.Name),
950 			"OControlImport::implTranslateValueProperty: invalid property name!");
951 
952 		// retrieve the type of the property
953 		Property aProp = _rxPropInfo->getPropertyByName(_rPropValue.Name);
954 		// the untranslated string value as read in handleAttribute
955 		::rtl::OUString sValue;
956     #if OSL_DEBUG_LEVEL > 0
957 		sal_Bool bSuccess =
958 	#endif
959 		_rPropValue.Value >>= sValue;
960 		OSL_ENSURE(bSuccess, "OControlImport::implTranslateValueProperty: supposed to be called with non-translated string values!");
961 
962 		if (TypeClass_ANY == aProp.Type.getTypeClass())
963 		{
964 			// we have exactly 2 properties where this type class is allowed:
965 			OSL_ENSURE(
966 					(0 == _rPropValue.Name.compareToAscii(PROPERTY_EFFECTIVE_VALUE))
967 				||	(0 == _rPropValue.Name.compareToAscii(PROPERTY_EFFECTIVE_DEFAULT)),
968 				"OControlImport::implTranslateValueProperty: invalid property type/name combination!");
969 
970 			// Both properties are allowed to have a double or a string value,
971 			// so first try to convert the string into a number
972 			double nValue;
973 			if (GetImport().GetMM100UnitConverter().convertDouble(nValue, sValue))
974 				_rPropValue.Value <<= nValue;
975 			else
976 				_rPropValue.Value <<= sValue;
977 		}
978 		else
979 			_rPropValue.Value = PropertyConversion::convertString(GetImport(), aProp.Type, sValue);
980 	}
981 
982 	//---------------------------------------------------------------------
983 	void OControlImport::EndElement()
984 	{
985 		OSL_ENSURE(m_xElement.is(), "OControlImport::EndElement: invalid control!");
986 		if ( !m_xElement.is() )
987 			return;
988 
989 		// register our control with it's id
990 		if (m_sControlId.getLength())
991 			m_rFormImport.registerControlId(m_xElement, m_sControlId);
992 		// it's allowed to have no control id. In this case we're importing a column
993 
994 		// one more pre-work to do:
995 		// when we set default values, then by definition the respective value is set
996 		// to this default value, too. This means if the sequence contains for example
997 		// a DefaultText value, then the Text will be affected by this, too.
998 		// In case the Text is not part of the property sequence (or occurs _before_
999 		// the DefaultText, which can happen for other value/default-value property names),
1000 		// this means that the Text (the value property) is incorrectly imported.
1001 		// #102475# - 04.09.2002 - fs@openoffice.org
1002 
1003 		sal_Bool bRestoreValuePropertyValue = sal_False;
1004 		Any aValuePropertyValue;
1005 
1006 		sal_Int16 nClassId = FormComponentType::CONTROL;
1007 		try
1008 		{
1009 			// get the class id of our element
1010 			m_xElement->getPropertyValue(PROPERTY_CLASSID) >>= nClassId;
1011 		}
1012 		catch( const Exception& )
1013 		{
1014 			OSL_ENSURE( sal_False, "OControlImport::EndElement: caught an exception while retrieving the class id!" );
1015 		}
1016 
1017 		const sal_Char* pValueProperty = NULL;
1018 		const sal_Char* pDefaultValueProperty = NULL;
1019 		getRuntimeValuePropertyNames(m_eElementType, nClassId, pValueProperty, pDefaultValueProperty);
1020 		if ( pDefaultValueProperty && pValueProperty )
1021 		{
1022 			sal_Bool bNonDefaultValuePropertyValue = sal_False;
1023 				// is the "value property" part of the sequence?
1024 
1025 			// look up this property in our sequence
1026             PropertyValueArray::iterator aEnd = m_aValues.end();
1027 			for (	PropertyValueArray::iterator aCheck = m_aValues.begin();
1028 					( aCheck != aEnd );
1029 					++aCheck
1030 				)
1031 			{
1032 				if ( aCheck->Name.equalsAscii( pDefaultValueProperty ) )
1033 					bRestoreValuePropertyValue = sal_True;
1034 				else if ( aCheck->Name.equalsAscii( pValueProperty ) )
1035 				{
1036 					bNonDefaultValuePropertyValue = sal_True;
1037 					// we need to restore the value property we found here, nothing else
1038 					aValuePropertyValue = aCheck->Value;
1039 				}
1040 			}
1041 
1042 			if ( bRestoreValuePropertyValue && !bNonDefaultValuePropertyValue )
1043 			{
1044 				// found it -> need to remember (and restore) the "value property value", which is not set explicitly
1045 				try
1046 				{
1047 					aValuePropertyValue = m_xElement->getPropertyValue( ::rtl::OUString::createFromAscii( pValueProperty ) );
1048 				}
1049 				catch( const Exception& )
1050 				{
1051 					OSL_ENSURE( sal_False, "OControlImport::EndElement: caught an exception while retrieving the current value property!" );
1052 				}
1053 			}
1054 		}
1055 
1056 		// let the base class set all the values
1057 		OElementImport::EndElement();
1058 
1059 		// restore the "value property value", if necessary
1060 		if ( bRestoreValuePropertyValue && pValueProperty )
1061 		{
1062 			try
1063 			{
1064 				m_xElement->setPropertyValue( ::rtl::OUString::createFromAscii( pValueProperty ), aValuePropertyValue );
1065 			}
1066 			catch( const Exception& )
1067 			{
1068 				OSL_ENSURE( sal_False, "OControlImport::EndElement: caught an exception while restoring the value property!" );
1069 			}
1070 		}
1071 
1072         // the external cell binding, if applicable
1073         if ( m_xElement.is() && m_sBoundCellAddress.getLength() )
1074             doRegisterCellValueBinding( m_sBoundCellAddress );
1075 
1076         // XForms binding, if applicable
1077         if ( m_xElement.is() && m_sBindingID.getLength() )
1078             doRegisterXFormsValueBinding( m_sBindingID );
1079 
1080         // XForms list binding, if applicable
1081         if ( m_xElement.is() && m_sListBindingID.getLength() )
1082             doRegisterXFormsListBinding( m_sListBindingID );
1083 
1084         // XForms submission, if applicable
1085         if ( m_xElement.is() && m_sSubmissionID.getLength() )
1086             doRegisterXFormsSubmission( m_sSubmissionID );
1087 	}
1088 
1089 	//---------------------------------------------------------------------
1090     void OControlImport::doRegisterCellValueBinding( const ::rtl::OUString& _rBoundCellAddress )
1091     {
1092         OSL_PRECOND( m_xElement.is(), "OControlImport::doRegisterCellValueBinding: invalid element!" );
1093         OSL_PRECOND( _rBoundCellAddress.getLength(),
1094             "OControlImport::doRegisterCellValueBinding: invalid address!" );
1095 
1096         m_rContext.registerCellValueBinding( m_xElement, _rBoundCellAddress );
1097     }
1098 
1099     //---------------------------------------------------------------------
1100     void OControlImport::doRegisterXFormsValueBinding( const ::rtl::OUString& _rBindingID )
1101     {
1102         OSL_PRECOND( m_xElement.is(), "need element" );
1103         OSL_PRECOND( _rBindingID.getLength() > 0, "binding ID is not valid" );
1104 
1105         m_rContext.registerXFormsValueBinding( m_xElement, _rBindingID );
1106     }
1107 
1108     //---------------------------------------------------------------------
1109     void OControlImport::doRegisterXFormsListBinding( const ::rtl::OUString& _rBindingID )
1110     {
1111         OSL_PRECOND( m_xElement.is(), "need element" );
1112         OSL_PRECOND( _rBindingID.getLength() > 0, "binding ID is not valid" );
1113 
1114         m_rContext.registerXFormsListBinding( m_xElement, _rBindingID );
1115     }
1116 
1117     //---------------------------------------------------------------------
1118     void OControlImport::doRegisterXFormsSubmission( const ::rtl::OUString& _rSubmissionID )
1119     {
1120         OSL_PRECOND( m_xElement.is(), "need element" );
1121         OSL_PRECOND( _rSubmissionID.getLength() > 0, "binding ID is not valid" );
1122 
1123         m_rContext.registerXFormsSubmission( m_xElement, _rSubmissionID );
1124     }
1125 
1126     //---------------------------------------------------------------------
1127 	//added by BerryJia for fixing bug102407 2002-11-5
1128 	Reference< XPropertySet > OControlImport::createElement()
1129 	{
1130 		const Reference<XPropertySet> xPropSet = OElementImport::createElement();
1131 		if ( xPropSet.is() )
1132 		{
1133             m_xInfo = xPropSet->getPropertySetInfo();
1134 			if ( m_xInfo.is() && m_xInfo->hasPropertyByName(PROPERTY_ALIGN) )
1135 			{
1136 				Any aValue;
1137 				xPropSet->setPropertyValue(PROPERTY_ALIGN,aValue);
1138 			}
1139 		}
1140 		return xPropSet;
1141 	}
1142 
1143 	//=====================================================================
1144 	//= OImagePositionImport
1145 	//=====================================================================
1146 	//---------------------------------------------------------------------
1147     OImagePositionImport::OImagePositionImport( OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager,
1148         sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, const Reference< XNameContainer >& _rxParentContainer,
1149 		OControlElement::ElementType _eType )
1150         :OControlImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType )
1151         ,m_nImagePosition( -1 )
1152         ,m_nImageAlign( 0 )
1153         ,m_bHaveImagePosition( sal_False )
1154     {
1155     }
1156 
1157 	//---------------------------------------------------------------------
1158     bool OImagePositionImport::handleAttribute( sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName,
1159         const ::rtl::OUString& _rValue )
1160     {
1161         if ( _rLocalName == GetXMLToken( XML_IMAGE_POSITION ) )
1162         {
1163             OSL_VERIFY( PropertyConversion::convertString(
1164                 m_rContext.getGlobalContext(), ::getCppuType( &m_nImagePosition ),
1165                 _rValue, OEnumMapper::getEnumMap( OEnumMapper::epImagePosition )
1166             ) >>= m_nImagePosition );
1167             m_bHaveImagePosition = sal_True;
1168             return true;
1169         }
1170 
1171         if ( _rLocalName == GetXMLToken( XML_IMAGE_ALIGN ) )
1172         {
1173             OSL_VERIFY( PropertyConversion::convertString(
1174                 m_rContext.getGlobalContext(), ::getCppuType( &m_nImageAlign ),
1175                 _rValue, OEnumMapper::getEnumMap( OEnumMapper::epImageAlign )
1176             ) >>= m_nImageAlign );
1177             return true;
1178         }
1179 
1180         return OControlImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue );
1181     }
1182 
1183 	//---------------------------------------------------------------------
1184 	void OImagePositionImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1185 	{
1186 		OControlImport::StartElement( _rxAttrList );
1187 
1188         if ( m_bHaveImagePosition )
1189         {
1190             sal_Int16 nUnoImagePosition = ImagePosition::Centered;
1191             if ( m_nImagePosition >= 0 )
1192             {
1193                 OSL_ENSURE( ( m_nImagePosition <= 3 ) && ( m_nImageAlign >= 0 ) && ( m_nImageAlign < 3 ),
1194                     "OImagePositionImport::StartElement: unknown image align and/or position!" );
1195                 nUnoImagePosition = m_nImagePosition * 3 + m_nImageAlign;
1196             }
1197 
1198             PropertyValue aImagePosition;
1199 		    aImagePosition.Name = PROPERTY_IMAGE_POSITION;
1200 		    aImagePosition.Value <<= nUnoImagePosition;
1201 		    implPushBackPropertyValue( aImagePosition );
1202         }
1203 	}
1204 
1205     //=====================================================================
1206 	//= OReferredControlImport
1207 	//=====================================================================
1208 	//---------------------------------------------------------------------
1209 	OReferredControlImport::OReferredControlImport(
1210 			OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1211 			const Reference< XNameContainer >& _rxParentContainer,
1212 			OControlElement::ElementType )
1213 		:OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer)
1214 	{
1215 	}
1216 
1217 	//---------------------------------------------------------------------
1218 	void OReferredControlImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1219 	{
1220 		OControlImport::StartElement(_rxAttrList);
1221 
1222 		// the base class should have created the control, so we can register it
1223 		if ( m_sReferringControls.getLength() )
1224 			m_rFormImport.registerControlReferences(m_xElement, m_sReferringControls);
1225 	}
1226 
1227 	//---------------------------------------------------------------------
1228 	bool OReferredControlImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName,
1229 		const ::rtl::OUString& _rValue)
1230 	{
1231 		static const ::rtl::OUString s_sReferenceAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_FOR));
1232 		if (_rLocalName == s_sReferenceAttributeName)
1233         {
1234 			m_sReferringControls = _rValue;
1235             return true;
1236         }
1237 		return OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue);
1238 	}
1239 
1240 	//=====================================================================
1241 	//= OPasswordImport
1242 	//=====================================================================
1243 	//---------------------------------------------------------------------
1244 	OPasswordImport::OPasswordImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1245 			const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType)
1246 		:OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType)
1247 	{
1248 	}
1249 
1250 	//---------------------------------------------------------------------
1251 	bool OPasswordImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
1252 	{
1253 		static const ::rtl::OUString s_sEchoCharAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getSpecialAttributeName(SCA_ECHO_CHAR));
1254 		if (_rLocalName == s_sEchoCharAttributeName)
1255 		{
1256 			// need a special handling for the EchoChar property
1257 			PropertyValue aEchoChar;
1258 			aEchoChar.Name = PROPERTY_ECHOCHAR;
1259 			OSL_ENSURE(_rValue.getLength() == 1, "OPasswordImport::handleAttribute: invalid echo char attribute!");
1260 				// we ourself should not have written values other than of length 1
1261 			if (_rValue.getLength() >= 1)
1262 				aEchoChar.Value <<= (sal_Int16)_rValue.getStr()[0];
1263 			else
1264 				aEchoChar.Value <<= (sal_Int16)0;
1265 			implPushBackPropertyValue(aEchoChar);
1266             return true;
1267 		}
1268 		return OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue);
1269 	}
1270 
1271 	//=====================================================================
1272 	//= ORadioImport
1273 	//=====================================================================
1274 	//---------------------------------------------------------------------
1275 	ORadioImport::ORadioImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1276 			const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType)
1277 		:OImagePositionImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType )
1278 	{
1279 	}
1280 
1281 	//---------------------------------------------------------------------
1282 	bool ORadioImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
1283 	{
1284 		// need special handling for the State & CurrentState properties:
1285 		// they're stored as booleans, but expected to be int16 properties
1286         static const sal_Char* pCurrentSelectedAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_SELECTED);
1287 		static const sal_Char* pSelectedAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_SELECTED);
1288 		if  (  _rLocalName.equalsAscii( pCurrentSelectedAttributeName )
1289             || _rLocalName.equalsAscii( pSelectedAttributeName )
1290             )
1291 		{
1292 			const OAttribute2Property::AttributeAssignment* pProperty = m_rContext.getAttributeMap().getAttributeTranslation(_rLocalName);
1293 			OSL_ENSURE(pProperty, "ORadioImport::handleAttribute: invalid property map!");
1294 			if (pProperty)
1295 			{
1296 				const Any aBooleanValue( PropertyConversion::convertString(m_rContext.getGlobalContext(), pProperty->aPropertyType, _rValue, pProperty->pEnumMap) );
1297 
1298 				// create and store a new PropertyValue
1299 				PropertyValue aNewValue;
1300 				aNewValue.Name = pProperty->sPropertyName;
1301 				aNewValue.Value <<= (sal_Int16)::cppu::any2bool(aBooleanValue);
1302 
1303 				implPushBackPropertyValue(aNewValue);
1304 			}
1305             return true;
1306 		}
1307 		return OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue );
1308 	}
1309 
1310 	//=====================================================================
1311 	//= OURLReferenceImport
1312 	//=====================================================================
1313 	OURLReferenceImport::OURLReferenceImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1314 			const Reference< XNameContainer >& _rxParentContainer,
1315 			OControlElement::ElementType _eType)
1316 		:OImagePositionImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType)
1317 	{
1318 	}
1319 
1320 	//---------------------------------------------------------------------
1321 	bool OURLReferenceImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
1322 	{
1323 		static const sal_Char* s_pTargetLocationAttributeName	= OAttributeMetaData::getCommonControlAttributeName( CCA_TARGET_LOCATION );
1324 		static const sal_Char* s_pImageDataAttributeName		= OAttributeMetaData::getCommonControlAttributeName( CCA_IMAGE_DATA );
1325 
1326 		// need to make the URL absolute if
1327 		// * it's the image-data attribute
1328 		// * it's the target-location attribute, and we're dealign with an object which has the respective property
1329 		sal_Bool bMakeAbsolute =
1330 				( 0 == _rLocalName.compareToAscii( s_pImageDataAttributeName ) )
1331 			||	(	( 0 == _rLocalName.compareToAscii( s_pTargetLocationAttributeName ) )
1332 				&&	(	( OControlElement::BUTTON == m_eElementType )
1333 					||	( OControlElement::IMAGE == m_eElementType )
1334 					)
1335 				);
1336 
1337 		if ( bMakeAbsolute && ( _rValue.getLength() > 0  ) )
1338 		{
1339 			// make a global URL out of the local one
1340             ::rtl::OUString sAdjustedValue;
1341             // only resolve image related url
1342             // we don't want say form url targets to be resolved
1343             // using ResolveGraphicObjectURL
1344             if ( 0 == _rLocalName.compareToAscii( s_pImageDataAttributeName ) )
1345                 sAdjustedValue = m_rContext.getGlobalContext().ResolveGraphicObjectURL( _rValue, sal_False );
1346             else
1347                 sAdjustedValue = m_rContext.getGlobalContext().GetAbsoluteReference( _rValue );
1348             return OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, sAdjustedValue );
1349 		}
1350 
1351 		return OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue );
1352 	}
1353 
1354 	//=====================================================================
1355 	//= OButtonImport
1356 	//=====================================================================
1357 	//---------------------------------------------------------------------
1358 	OButtonImport::OButtonImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1359 			const Reference< XNameContainer >& _rxParentContainer,
1360 			OControlElement::ElementType _eType)
1361 		:OURLReferenceImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType)
1362 	{
1363 		enableTrackAttributes();
1364 	}
1365 
1366 	//---------------------------------------------------------------------
1367 	void OButtonImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1368 	{
1369 		OURLReferenceImport::StartElement(_rxAttrList);
1370 
1371 		// handle the target-frame attribute
1372 		simulateDefaultedAttribute(OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_FRAME), PROPERTY_TARGETFRAME, "_blank");
1373 	}
1374 
1375 	//=====================================================================
1376 	//= OValueRangeImport
1377 	//=====================================================================
1378 	//---------------------------------------------------------------------
1379 	OValueRangeImport::OValueRangeImport( OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1380 			const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType )
1381 		:OControlImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType )
1382         ,m_nStepSizeValue( 1 )
1383 	{
1384 
1385 	}
1386 
1387 	//---------------------------------------------------------------------
1388 	bool OValueRangeImport::handleAttribute( sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue )
1389     {
1390         if ( _rLocalName.equalsAscii( OAttributeMetaData::getSpecialAttributeName( SCA_STEP_SIZE ) ) )
1391         {
1392     		GetImport().GetMM100UnitConverter().convertNumber( m_nStepSizeValue, _rValue );
1393             return true;
1394         }
1395         return OControlImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue );
1396     }
1397 
1398 	//---------------------------------------------------------------------
1399 	void OValueRangeImport::StartElement( const Reference< sax::XAttributeList >& _rxAttrList )
1400 	{
1401 		OControlImport::StartElement( _rxAttrList );
1402 
1403         if ( m_xInfo.is() )
1404         {
1405             if ( m_xInfo->hasPropertyByName( PROPERTY_SPIN_INCREMENT ) )
1406                 m_xElement->setPropertyValue( PROPERTY_SPIN_INCREMENT, makeAny( m_nStepSizeValue ) );
1407             else if ( m_xInfo->hasPropertyByName( PROPERTY_LINE_INCREMENT ) )
1408                 m_xElement->setPropertyValue( PROPERTY_LINE_INCREMENT, makeAny( m_nStepSizeValue ) );
1409 		}
1410 	}
1411 
1412 	//=====================================================================
1413 	//= OTextLikeImport
1414 	//=====================================================================
1415 	//---------------------------------------------------------------------
1416 	OTextLikeImport::OTextLikeImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1417 			const Reference< XNameContainer >& _rxParentContainer,
1418 			OControlElement::ElementType _eType)
1419 		:OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType)
1420         ,m_bEncounteredTextPara( false )
1421 	{
1422 		enableTrackAttributes();
1423 	}
1424 
1425 	//---------------------------------------------------------------------
1426     SvXMLImportContext* OTextLikeImport::CreateChildContext( sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
1427         const Reference< sax::XAttributeList >& _rxAttrList )
1428     {
1429 		if ( ( XML_NAMESPACE_TEXT == _nPrefix ) && _rLocalName.equalsIgnoreAsciiCaseAscii( "p" ) )
1430         {
1431             OSL_ENSURE( m_eElementType == OControlElement::TEXT_AREA,
1432                 "OTextLikeImport::CreateChildContext: text paragraphs in a non-text-area?" );
1433 
1434             if ( m_eElementType == OControlElement::TEXT_AREA )
1435             {
1436                 Reference< XText > xTextElement( m_xElement, UNO_QUERY );
1437                 if ( xTextElement.is() )
1438                 {
1439                     UniReference < XMLTextImportHelper > xTextImportHelper( m_rContext.getGlobalContext().GetTextImport() );
1440 
1441                     if ( !m_xCursor.is() )
1442                     {
1443 				        m_xOldCursor = xTextImportHelper->GetCursor();
1444 				        m_xCursor = xTextElement->createTextCursor();
1445 
1446                         if ( m_xCursor.is() )
1447 					        xTextImportHelper->SetCursor( m_xCursor );
1448                     }
1449                     if ( m_xCursor.is() )
1450                     {
1451                         m_bEncounteredTextPara = true;
1452 			            return xTextImportHelper->CreateTextChildContext( m_rContext.getGlobalContext(), _nPrefix, _rLocalName, _rxAttrList );
1453                     }
1454                 }
1455                 else
1456                 {
1457                     // in theory, we could accumulate all the text portions (without formatting),
1458                     // and set it as Text property at the model ...
1459                 }
1460             }
1461         }
1462 
1463         return OControlImport::CreateChildContext( _nPrefix, _rLocalName, _rxAttrList );
1464     }
1465 
1466 	//---------------------------------------------------------------------
1467 	void OTextLikeImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1468 	{
1469 		OControlImport::StartElement(_rxAttrList);
1470 
1471 		// handle the convert-empty-to-null attribute, whose default is different from the property default
1472 		// unfortunately, different classes are imported by this class ('cause they're represented by the
1473 		// same XML element), though not all of them know this property.
1474 		// So we have to do a check ...
1475 		if (m_xElement.is() && m_xInfo.is() && m_xInfo->hasPropertyByName(PROPERTY_EMPTY_IS_NULL) )
1476 			simulateDefaultedAttribute(OAttributeMetaData::getDatabaseAttributeName(DA_CONVERT_EMPTY), PROPERTY_EMPTY_IS_NULL, "false");
1477 	}
1478 
1479 	//---------------------------------------------------------------------
1480     struct EqualHandle : public ::std::unary_function< PropertyValue, bool >
1481     {
1482         const sal_Int32 m_nHandle;
1483         EqualHandle( sal_Int32 _nHandle ) : m_nHandle( _nHandle ) { }
1484 
1485         inline bool operator()( const PropertyValue& _rProp )
1486         {
1487             return _rProp.Handle == m_nHandle;
1488         }
1489     };
1490 
1491 	//---------------------------------------------------------------------
1492 	void OTextLikeImport::removeRedundantCurrentValue()
1493     {
1494         if ( m_bEncounteredTextPara )
1495         {
1496             // In case the text is written in the text:p elements, we need to ignore what we read as
1497             // current-value attribute, since it's redundant.
1498             // fortunately, OElementImport tagged the value property with the PROPID_CURRENT_VALUE
1499             // handle, so we do not need to determine the name of our value property here
1500             // (normally, it should be "Text", since no other controls than the edit field should
1501             // have the text:p elements)
1502             PropertyValueArray::iterator aValuePropertyPos = ::std::find_if(
1503                 m_aValues.begin(),
1504                 m_aValues.end(),
1505                 EqualHandle( PROPID_CURRENT_VALUE )
1506             );
1507             if ( aValuePropertyPos != m_aValues.end() )
1508             {
1509                 OSL_ENSURE( aValuePropertyPos->Name == PROPERTY_TEXT, "OTextLikeImport::EndElement: text:p was present, but our value property is *not* 'Text'!" );
1510                 if ( aValuePropertyPos->Name == PROPERTY_TEXT )
1511                 {
1512                     ::std::copy(
1513                         aValuePropertyPos + 1,
1514                         m_aValues.end(),
1515                         aValuePropertyPos
1516                     );
1517                     m_aValues.resize( m_aValues.size() - 1 );
1518                 }
1519             }
1520 
1521             // additionally, we need to set the "RichText" property of our element to sal_True
1522             // (the presence of the text:p is used as indicator for the value of the RichText property)
1523             sal_Bool bHasRichTextProperty = sal_False;
1524 			if ( m_xInfo.is() )
1525 				bHasRichTextProperty = m_xInfo->hasPropertyByName( PROPERTY_RICH_TEXT );
1526             OSL_ENSURE( bHasRichTextProperty, "OTextLikeImport::EndElement: text:p, but no rich text control?" );
1527             if ( bHasRichTextProperty )
1528                 m_xElement->setPropertyValue( PROPERTY_RICH_TEXT, makeAny( (sal_Bool)sal_True ) );
1529         }
1530         // Note that we do *not* set the RichText property (in case our element has one) to sal_False here
1531         // since this is the default of this property, anyway.
1532     }
1533 
1534 	//---------------------------------------------------------------------
1535     struct EqualName : public ::std::unary_function< PropertyValue, bool >
1536     {
1537         const ::rtl::OUString m_sName;
1538         EqualName( const ::rtl::OUString& _rName ) : m_sName( _rName ) { }
1539 
1540         inline bool operator()( const PropertyValue& _rProp )
1541         {
1542             return _rProp.Name == m_sName;
1543         }
1544     };
1545 
1546 	//---------------------------------------------------------------------
1547     void OTextLikeImport::adjustDefaultControlProperty()
1548     {
1549         // In OpenOffice.org 2.0, we changed the implementation of the css.form.component.TextField (the model of a text field control),
1550         // so that it now uses another default control. So if we encounter a text field where the *old* default
1551         // control property is writting, we are not allowed to use it
1552         PropertyValueArray::iterator aDefaultControlPropertyPos = ::std::find_if(
1553             m_aValues.begin(),
1554             m_aValues.end(),
1555             EqualName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultControl" ) ) )
1556         );
1557         if ( aDefaultControlPropertyPos != m_aValues.end() )
1558         {
1559             ::rtl::OUString sDefaultControl;
1560             OSL_VERIFY( aDefaultControlPropertyPos->Value >>= sDefaultControl );
1561             if ( sDefaultControl.equalsAscii( "stardiv.one.form.control.Edit" ) )
1562             {
1563                 // complete remove this property value from the array. Today's "default value" of the "DefaultControl"
1564                 // property is sufficient
1565                 ::std::copy(
1566                     aDefaultControlPropertyPos + 1,
1567                     m_aValues.end(),
1568                     aDefaultControlPropertyPos
1569                 );
1570                 m_aValues.resize( m_aValues.size() - 1 );
1571             }
1572         }
1573     }
1574 
1575 	//---------------------------------------------------------------------
1576 	void OTextLikeImport::EndElement()
1577     {
1578         removeRedundantCurrentValue();
1579         adjustDefaultControlProperty();
1580 
1581         // let the base class do the stuff
1582         OControlImport::EndElement();
1583 
1584         // some cleanups
1585         UniReference < XMLTextImportHelper > xTextImportHelper( m_rContext.getGlobalContext().GetTextImport() );
1586         if ( m_xCursor.is() )
1587 	    {
1588 		    // delete the newline which has been imported errornously
1589             // TODO (fs): stole this code somewhere - why don't we fix the text import??
1590 		    m_xCursor->gotoEnd( sal_False );
1591 		    m_xCursor->goLeft( 1, sal_True );
1592             m_xCursor->setString( ::rtl::OUString() );
1593 
1594 		    // reset cursor
1595 		    xTextImportHelper->ResetCursor();
1596 	    }
1597 
1598         if ( m_xOldCursor.is() )
1599 		    xTextImportHelper->SetCursor( m_xOldCursor );
1600 
1601     }
1602 
1603 	//=====================================================================
1604 	//= OListAndComboImport
1605 	//=====================================================================
1606 	//---------------------------------------------------------------------
1607 	OListAndComboImport::OListAndComboImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1608 			const Reference< XNameContainer >& _rxParentContainer,
1609 			OControlElement::ElementType _eType)
1610 		:OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType)
1611 		,m_nEmptyListItems( 0 )
1612 		,m_nEmptyValueItems( 0 )
1613 		,m_bEncounteredLSAttrib( sal_False )
1614         ,m_bLinkWithIndexes( sal_False )
1615 	{
1616 		if (OControlElement::COMBOBOX == m_eElementType)
1617 			enableTrackAttributes();
1618 	}
1619 
1620 	//---------------------------------------------------------------------
1621 	SvXMLImportContext* OListAndComboImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
1622 			const Reference< sax::XAttributeList >& _rxAttrList)
1623 	{
1624 		// is it the "option" sub tag of a listbox ?
1625 		static const ::rtl::OUString s_sOptionElementName = ::rtl::OUString::createFromAscii("option");
1626 		if (s_sOptionElementName == _rLocalName)
1627 			return new OListOptionImport(GetImport(), _nPrefix, _rLocalName, this);
1628 
1629 		// is it the "item" sub tag of a combobox ?
1630 		static const ::rtl::OUString s_sItemElementName = ::rtl::OUString::createFromAscii("item");
1631 		if (s_sItemElementName == _rLocalName)
1632 			return new OComboItemImport(GetImport(), _nPrefix, _rLocalName, this);
1633 
1634 		// everything else
1635 		return OControlImport::CreateChildContext(_nPrefix, _rLocalName, _rxAttrList);
1636 	}
1637 
1638 	//---------------------------------------------------------------------
1639 	void OListAndComboImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1640 	{
1641         m_bLinkWithIndexes = sal_False;
1642 
1643 		OControlImport::StartElement(_rxAttrList);
1644 
1645 		if (OControlElement::COMBOBOX == m_eElementType)
1646 		{
1647 			// for the auto-completion
1648 			// the attribute default does not equal the property default, so in case we did not read this attribute,
1649 			// we have to simulate it
1650 			simulateDefaultedAttribute( OAttributeMetaData::getSpecialAttributeName( SCA_AUTOMATIC_COMPLETION ), PROPERTY_AUTOCOMPLETE, "false");
1651 
1652 			// same for the convert-empty-to-null attribute, which's default is different from the property default
1653 			simulateDefaultedAttribute( OAttributeMetaData::getDatabaseAttributeName( DA_CONVERT_EMPTY ), PROPERTY_EMPTY_IS_NULL, "false");
1654 		}
1655 	}
1656 
1657 	//---------------------------------------------------------------------
1658 	void OListAndComboImport::EndElement()
1659 	{
1660 		// append the list source property the the properties sequence of our importer
1661 		// the string item list
1662 		PropertyValue aItemList;
1663 		aItemList.Name = PROPERTY_STRING_ITEM_LIST;
1664 		aItemList.Value <<= m_aListSource;
1665 		implPushBackPropertyValue(aItemList);
1666 
1667 		if (OControlElement::LISTBOX == m_eElementType)
1668 		{
1669 			OSL_ENSURE((m_aListSource.getLength() + m_nEmptyListItems) == (m_aValueList.getLength() + m_nEmptyValueItems),
1670 				"OListAndComboImport::EndElement: inconsistence between labels and values!");
1671 
1672 			if ( !m_bEncounteredLSAttrib )
1673 			{
1674 				// the value sequence
1675 				PropertyValue aValueList;
1676 				aValueList.Name = PROPERTY_LISTSOURCE;
1677 				aValueList.Value <<= m_aValueList;
1678 				implPushBackPropertyValue(aValueList);
1679 			}
1680 
1681 			// the select sequence
1682 			PropertyValue aSelected;
1683 			aSelected.Name = PROPERTY_SELECT_SEQ;
1684 			aSelected.Value <<= m_aSelectedSeq;
1685 			implPushBackPropertyValue(aSelected);
1686 
1687 			// the default select sequence
1688 			PropertyValue aDefaultSelected;
1689 			aDefaultSelected.Name = PROPERTY_DEFAULT_SELECT_SEQ;
1690 			aDefaultSelected.Value <<= m_aDefaultSelectedSeq;
1691 			implPushBackPropertyValue(aDefaultSelected);
1692 		}
1693 
1694 		OControlImport::EndElement();
1695 
1696         // the external list source, if applicable
1697         if ( m_xElement.is() && m_sCellListSource.getLength() )
1698             m_rContext.registerCellRangeListSource( m_xElement, m_sCellListSource );
1699 	}
1700 
1701 	//---------------------------------------------------------------------
1702 	void OListAndComboImport::doRegisterCellValueBinding( const ::rtl::OUString& _rBoundCellAddress )
1703     {
1704         ::rtl::OUString sBoundCellAddress( _rBoundCellAddress );
1705         if ( m_bLinkWithIndexes )
1706         {
1707             // This is a HACK. We register a string which is no valid address, but allows
1708             // (somewhere else) to determine that a non-standard binding should be created.
1709             // This hack is acceptable for OOo 1.1.1, since the file format for value
1710             // bindings of form controls is to be changed afterwards, anyway.
1711             sBoundCellAddress += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":index" ) );
1712         }
1713 
1714         OControlImport::doRegisterCellValueBinding( sBoundCellAddress );
1715     }
1716 
1717 	//---------------------------------------------------------------------
1718 	bool OListAndComboImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
1719 	{
1720         static const sal_Char* pListSourceAttributeName = OAttributeMetaData::getDatabaseAttributeName(DA_LIST_SOURCE);
1721 		if ( _rLocalName.equalsAscii(pListSourceAttributeName) )
1722 		{
1723 			PropertyValue aListSource;
1724 			aListSource.Name = PROPERTY_LISTSOURCE;
1725 
1726 			// it's the ListSource attribute
1727 			m_bEncounteredLSAttrib = sal_True;
1728 			if ( OControlElement::COMBOBOX == m_eElementType )
1729 			{
1730 				aListSource.Value <<= _rValue;
1731 			}
1732 			else
1733 			{
1734 				// a listbox which has a list-source attribute must have a list-source-type of something
1735 				// not equal to ValueList.
1736 				// In this case, the list-source value is simply the one and only element of the ListSource property.
1737 				Sequence< ::rtl::OUString > aListSourcePropValue( 1 );
1738 				aListSourcePropValue[0] = _rValue;
1739 				aListSource.Value <<= aListSourcePropValue;
1740 			}
1741 
1742 			implPushBackPropertyValue( aListSource );
1743             return true;
1744 		}
1745 
1746         if ( _rLocalName.equalsAscii( OAttributeMetaData::getBindingAttributeName( BA_LIST_CELL_RANGE ) ) )
1747         {
1748             m_sCellListSource = _rValue;
1749             return true;
1750         }
1751 
1752 		if ( _rLocalName.equalsAscii( OAttributeMetaData::getBindingAttributeName( BA_LIST_LINKING_TYPE ) ) )
1753         {
1754             sal_Int16 nLinkageType = 0;
1755             PropertyConversion::convertString(
1756                 m_rContext.getGlobalContext(),
1757                 ::getCppuType( static_cast< sal_Int16* >( NULL ) ),
1758                 _rValue,
1759                 OEnumMapper::getEnumMap( OEnumMapper::epListLinkageType )
1760             ) >>= nLinkageType;
1761 
1762             m_bLinkWithIndexes = ( nLinkageType != 0 );
1763             return true;
1764         }
1765 
1766 		return OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue);
1767 	}
1768 
1769 	//---------------------------------------------------------------------
1770 	void OListAndComboImport::implPushBackLabel(const ::rtl::OUString& _rLabel)
1771 	{
1772 		OSL_ENSURE(!m_nEmptyListItems, "OListAndComboImport::implPushBackValue: label list is already done!");
1773 		if (!m_nEmptyListItems)
1774 			pushBackSequenceElement(m_aListSource, _rLabel);
1775 	}
1776 
1777 	//---------------------------------------------------------------------
1778 	void OListAndComboImport::implPushBackValue(const ::rtl::OUString& _rValue)
1779 	{
1780 		OSL_ENSURE(!m_nEmptyValueItems, "OListAndComboImport::implPushBackValue: value list is already done!");
1781 		if (!m_nEmptyValueItems)
1782 		{
1783 			OSL_ENSURE( !m_bEncounteredLSAttrib, "OListAndComboImport::implPushBackValue: invalid structure! Did you save this document with a version prior SRC641 m?" );
1784 				// We already had the list-source attribute, which means that the ListSourceType is
1785 				// not ValueList, which means that the ListSource should contain only one string in
1786 				// the first element of the sequence
1787 				// All other values in the file are invalid
1788 
1789 			pushBackSequenceElement( m_aValueList, _rValue );
1790 		}
1791 	}
1792 
1793 	//---------------------------------------------------------------------
1794 	void OListAndComboImport::implEmptyLabelFound()
1795 	{
1796 		++m_nEmptyListItems;
1797 	}
1798 
1799 	//---------------------------------------------------------------------
1800 	void OListAndComboImport::implEmptyValueFound()
1801 	{
1802 		++m_nEmptyValueItems;
1803 	}
1804 
1805 	//---------------------------------------------------------------------
1806 	void OListAndComboImport::implSelectCurrentItem()
1807 	{
1808 		OSL_ENSURE((m_aListSource.getLength() + m_nEmptyListItems) == (m_aValueList.getLength() + m_nEmptyValueItems),
1809 			"OListAndComboImport::implSelectCurrentItem: inconsistence between labels and values!");
1810 
1811 		sal_Int16 nItemNumber = (sal_Int16)(m_aListSource.getLength() - 1 + m_nEmptyListItems);
1812 		pushBackSequenceElement(m_aSelectedSeq, nItemNumber);
1813 	}
1814 
1815 	//---------------------------------------------------------------------
1816 	void OListAndComboImport::implDefaultSelectCurrentItem()
1817 	{
1818 		OSL_ENSURE((m_aListSource.getLength() + m_nEmptyListItems) == (m_aValueList.getLength() + m_nEmptyValueItems),
1819 			"OListAndComboImport::implDefaultSelectCurrentItem: inconsistence between labels and values!");
1820 
1821 		sal_Int16 nItemNumber = (sal_Int16)(m_aListSource.getLength() - 1 + m_nEmptyListItems);
1822 		pushBackSequenceElement(m_aDefaultSelectedSeq, nItemNumber);
1823 	}
1824 
1825 	//=====================================================================
1826 	//= OListOptionImport
1827 	//=====================================================================
1828 	//---------------------------------------------------------------------
1829 	OListOptionImport::OListOptionImport(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1830 			const OListAndComboImportRef& _rListBox)
1831 		:SvXMLImportContext(_rImport, _nPrefix, _rName)
1832 		,m_xListBoxImport(_rListBox)
1833 	{
1834 	}
1835 
1836 	//---------------------------------------------------------------------
1837 	void OListOptionImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1838 	{
1839 		// the label and the value
1840         const SvXMLNamespaceMap& rMap = GetImport().GetNamespaceMap();
1841 		const ::rtl::OUString sLabelAttribute = rMap.GetQNameByKey(
1842 			GetPrefix(), ::rtl::OUString::createFromAscii("label"));
1843 		const ::rtl::OUString sValueAttribute = rMap.GetQNameByKey(
1844 			GetPrefix(), ::rtl::OUString::createFromAscii("value"));
1845 
1846 		// -------------------
1847 		// the label attribute
1848 		::rtl::OUString sValue = _rxAttrList->getValueByName(sLabelAttribute);
1849 		sal_Bool bNonexistentAttribute = sal_False;
1850 		if (!sValue.getLength())
1851 			if (0 == _rxAttrList->getTypeByName(sLabelAttribute).getLength())
1852 				// this attribute does not really exist
1853 				bNonexistentAttribute = sal_True;
1854 
1855 		if (bNonexistentAttribute)
1856 			m_xListBoxImport->implEmptyLabelFound();
1857 		else
1858 			m_xListBoxImport->implPushBackLabel( sValue );
1859 
1860 		// -------------------
1861 		// the value attribute
1862 		sValue = _rxAttrList->getValueByName(sValueAttribute);
1863 		bNonexistentAttribute = sal_False;
1864 		if (!sValue.getLength())
1865 			if (0 == _rxAttrList->getTypeByName(sValueAttribute).getLength())
1866 				// this attribute does not really exist
1867 				bNonexistentAttribute = sal_True;
1868 
1869 		if (bNonexistentAttribute)
1870 			m_xListBoxImport->implEmptyValueFound();
1871 		else
1872 			m_xListBoxImport->implPushBackValue( sValue );
1873 
1874 		// the current-selected and selected
1875 		const ::rtl::OUString sSelectedAttribute = rMap.GetQNameByKey(
1876 			GetPrefix(), ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_SELECTED)));
1877 		const ::rtl::OUString sDefaultSelectedAttribute = rMap.GetQNameByKey(
1878 			GetPrefix(), ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_SELECTED)));
1879 
1880 		// propagate the selected flag
1881 		sal_Bool bSelected;
1882 		GetImport().GetMM100UnitConverter().convertBool(bSelected, _rxAttrList->getValueByName(sSelectedAttribute));
1883 		if (bSelected)
1884 			m_xListBoxImport->implSelectCurrentItem();
1885 
1886 		// same for the default selected
1887 		sal_Bool bDefaultSelected;
1888 		GetImport().GetMM100UnitConverter().convertBool(bDefaultSelected, _rxAttrList->getValueByName(sDefaultSelectedAttribute));
1889 		if (bDefaultSelected)
1890 			m_xListBoxImport->implDefaultSelectCurrentItem();
1891 
1892 		SvXMLImportContext::StartElement(_rxAttrList);
1893 	}
1894 
1895 	//=====================================================================
1896 	//= OComboItemImport
1897 	//=====================================================================
1898 	//---------------------------------------------------------------------
1899 	OComboItemImport::OComboItemImport(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1900 			const OListAndComboImportRef& _rListBox)
1901 		:SvXMLImportContext(_rImport, _nPrefix, _rName)
1902 		,m_xListBoxImport(_rListBox)
1903 	{
1904 	}
1905 
1906 	//---------------------------------------------------------------------
1907 	void OComboItemImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1908 	{
1909 		const ::rtl::OUString sLabelAttributeName = GetImport().GetNamespaceMap().GetQNameByKey(
1910 			GetPrefix(), ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_LABEL)));
1911 		m_xListBoxImport->implPushBackLabel(_rxAttrList->getValueByName(sLabelAttributeName));
1912 
1913 		SvXMLImportContext::StartElement(_rxAttrList);
1914 	}
1915 
1916 
1917 	//=====================================================================
1918 	//= OColumnWrapperImport
1919 	//=====================================================================
1920 	//---------------------------------------------------------------------
1921 	OColumnWrapperImport::OColumnWrapperImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1922 			const Reference< XNameContainer >& _rxParentContainer)
1923 		:SvXMLImportContext(_rImport.getGlobalContext(), _nPrefix, _rName)
1924 		,m_xParentContainer(_rxParentContainer)
1925         ,m_rFormImport(_rImport)
1926 		,m_rEventManager(_rEventManager)
1927 	{
1928 	}
1929 	//---------------------------------------------------------------------
1930 	SvXMLImportContext* OColumnWrapperImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
1931 		const Reference< sax::XAttributeList >&)
1932 	{
1933 		OControlImport* pReturn = implCreateChildContext(_nPrefix, _rLocalName, OElementNameMap::getElementType(_rLocalName));
1934 		if (pReturn)
1935 		{
1936 			OSL_ENSURE(m_xOwnAttributes.is(), "OColumnWrapperImport::CreateChildContext: had no form:column element!");
1937 			pReturn->addOuterAttributes(m_xOwnAttributes);
1938 		}
1939 		return pReturn;
1940 	}
1941 	//---------------------------------------------------------------------
1942 	void OColumnWrapperImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1943 	{
1944 		OSL_ENSURE(!m_xOwnAttributes.is(), "OColumnWrapperImport::StartElement: aready have the cloned list!");
1945 
1946 		// clone the attributes
1947 		Reference< XCloneable > xCloneList(_rxAttrList, UNO_QUERY);
1948 		OSL_ENSURE(xCloneList.is(), "OColumnWrapperImport::StartElement: AttributeList not cloneable!");
1949         if ( xCloneList.is() )
1950 		    m_xOwnAttributes = Reference< sax::XAttributeList >(xCloneList->createClone(), UNO_QUERY);
1951 		OSL_ENSURE(m_xOwnAttributes.is(), "OColumnWrapperImport::StartElement: no cloned list!");
1952 	}
1953 
1954 	//---------------------------------------------------------------------
1955 	OControlImport* OColumnWrapperImport::implCreateChildContext(
1956 			sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
1957 			OControlElement::ElementType _eType)
1958 	{
1959 		OSL_ENSURE(	(OControlElement::TEXT == _eType)
1960 				||	(OControlElement::TEXT_AREA == _eType)
1961 				||	(OControlElement::FORMATTED_TEXT == _eType)
1962 				||	(OControlElement::CHECKBOX == _eType)
1963 				||	(OControlElement::LISTBOX == _eType)
1964 				||	(OControlElement::COMBOBOX == _eType)
1965 				||	(OControlElement::TIME == _eType)
1966 				||	(OControlElement::DATE == _eType),
1967 				"OColumnWrapperImport::implCreateChildContext: invalid or unrecognized sub element!");
1968 
1969 		switch (_eType)
1970 		{
1971 			case OControlElement::COMBOBOX:
1972 			case OControlElement::LISTBOX:
1973 				return new OColumnImport<OListAndComboImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType );
1974 
1975 			case OControlElement::PASSWORD:
1976 				return new OColumnImport<OPasswordImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType );
1977 
1978 			case OControlElement::TEXT:
1979 			case OControlElement::TEXT_AREA:
1980 			case OControlElement::FORMATTED_TEXT:
1981 				return new OColumnImport< OTextLikeImport >( m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType );
1982 
1983 			default:
1984 				return new OColumnImport<OControlImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType );
1985 		}
1986 	}
1987 
1988 	//=====================================================================
1989 	//= OGridImport
1990 	//=====================================================================
1991 	//---------------------------------------------------------------------
1992 	OGridImport::OGridImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1993 			const Reference< XNameContainer >& _rxParentContainer,
1994 			OControlElement::ElementType _eType)
1995 		:OGridImport_Base(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, "column")
1996 	{
1997 		setElementType(_eType);
1998 	}
1999 
2000 	//---------------------------------------------------------------------
2001 	SvXMLImportContext*	OGridImport::implCreateControlWrapper(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName)
2002 	{
2003 		return new OColumnWrapperImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer);
2004 	}
2005 
2006 	//=====================================================================
2007 	//= OFormImport
2008 	//=====================================================================
2009 	//---------------------------------------------------------------------
2010 	OFormImport::OFormImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
2011 			const Reference< XNameContainer >& _rxParentContainer)
2012 		:OFormImport_Base(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, "control")
2013 	{
2014 		enableTrackAttributes();
2015 	}
2016 
2017 	//---------------------------------------------------------------------
2018 	SvXMLImportContext* OFormImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
2019 		const Reference< sax::XAttributeList >& _rxAttrList)
2020 	{
2021 		if( token::IsXMLToken(_rLocalName, token::XML_FORM) )
2022 			return new OFormImport( m_rFormImport, *this, _nPrefix, _rLocalName,
2023 									m_xMeAsContainer);
2024 		else if ( token::IsXMLToken(_rLocalName, token::XML_CONNECTION_RESOURCE) )
2025 			return new OXMLDataSourceImport(GetImport(), _nPrefix, _rLocalName, _rxAttrList,m_xElement);
2026 		else if( (token::IsXMLToken(_rLocalName, token::XML_EVENT_LISTENERS) &&
2027 				 (XML_NAMESPACE_OFFICE == _nPrefix)) ||
2028 			     token::IsXMLToken( _rLocalName, token::XML_PROPERTIES) )
2029 			return OElementImport::CreateChildContext( _nPrefix, _rLocalName,
2030 													   _rxAttrList );
2031 		else
2032 			return implCreateChildContext( _nPrefix, _rLocalName,
2033 						OElementNameMap::getElementType(_rLocalName) );
2034 	}
2035 
2036 	//---------------------------------------------------------------------
2037 	void OFormImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
2038 	{
2039 		m_rFormImport.enterEventContext();
2040 		OFormImport_Base::StartElement(_rxAttrList);
2041 
2042 		// handle the target-frame attribute
2043 		simulateDefaultedAttribute(OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_FRAME), PROPERTY_TARGETFRAME, "_blank");
2044 	}
2045 
2046 	//---------------------------------------------------------------------
2047 	void OFormImport::EndElement()
2048 	{
2049 		OFormImport_Base::EndElement();
2050 		m_rFormImport.leaveEventContext();
2051 	}
2052 
2053 	//---------------------------------------------------------------------
2054 	SvXMLImportContext*	OFormImport::implCreateControlWrapper(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName)
2055 	{
2056 		OSL_ENSURE( !this, "illegal call to OFormImport::implCreateControlWrapper" );
2057 		return new SvXMLImportContext(GetImport(), _nPrefix, _rLocalName );
2058 	}
2059 
2060 	//---------------------------------------------------------------------
2061 	bool OFormImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
2062 	{
2063 		// handle the master/details field attributes (they're way too special to let the OPropertyImport handle them)
2064 		static const ::rtl::OUString s_sMasterFieldsAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getFormAttributeName(faMasterFields));
2065 		static const ::rtl::OUString s_sDetailFieldsAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getFormAttributeName(faDetailFiels));
2066 
2067 		if ( s_sMasterFieldsAttributeName == _rLocalName )
2068         {
2069 			implTranslateStringListProperty(PROPERTY_MASTERFIELDS, _rValue);
2070             return true;
2071         }
2072 
2073         if ( s_sDetailFieldsAttributeName == _rLocalName )
2074         {
2075 			implTranslateStringListProperty(PROPERTY_DETAILFIELDS, _rValue);
2076             return true;
2077         }
2078 
2079 		return OFormImport_Base::handleAttribute(_nNamespaceKey, _rLocalName, _rValue);
2080 	}
2081 
2082 	//---------------------------------------------------------------------
2083 	void OFormImport::implTranslateStringListProperty(const ::rtl::OUString& _rPropertyName, const ::rtl::OUString& _rValue)
2084 	{
2085 		PropertyValue aProp;
2086 		aProp.Name = _rPropertyName;
2087 
2088 		Sequence< ::rtl::OUString > aList;
2089 
2090 		// split up the value string
2091 		if (_rValue.getLength())
2092 		{
2093 			// For the moment, we build a vector instead of a Sequence. It's easier to handle because of it's
2094 			// push_back method
2095 			::std::vector< ::rtl::OUString > aElements;
2096 			// estimate the number of tokens
2097 			sal_Int32 nEstimate = 0, nLength = _rValue.getLength();
2098 			const sal_Unicode* pChars = _rValue.getStr();
2099 			for (sal_Int32 i=0; i<nLength; ++i, ++pChars)
2100 				if (*pChars == ',')
2101 					++nEstimate;
2102 			aElements.reserve(nEstimate + 1);
2103 				// that's the worst case. If the string contains the separator character _quoted_, we reserved to much ...
2104 
2105 
2106 			sal_Int32 nElementStart = 0;
2107 			sal_Int32 nNextSep = 0;
2108 			sal_Int32 nElementLength;
2109 			::rtl::OUString sElement;
2110 			do
2111 			{
2112 				// extract the current element
2113 				nNextSep = SvXMLUnitConverter::indexOfComma(
2114                     _rValue, nElementStart);
2115 				if (-1 == nNextSep)
2116 					nNextSep = nLength;
2117 				sElement = _rValue.copy(nElementStart, nNextSep - nElementStart);
2118 
2119 				nElementLength = sElement.getLength();
2120 				// when writing the sequence, we quoted the single elements with " characters
2121 				OSL_ENSURE(	(nElementLength >= 2)
2122 						&&	(sElement.getStr()[0] == '"')
2123 						&&	(sElement.getStr()[nElementLength - 1] == '"'),
2124 						"OFormImport::implTranslateStringListProperty: invalid quoted element name.");
2125 				sElement = sElement.copy(1, nElementLength - 2);
2126 
2127 				aElements.push_back(sElement);
2128 
2129 				// swith to the next element
2130 				nElementStart = 1 + nNextSep;
2131 			}
2132 			while (nElementStart < nLength);
2133 
2134 			::rtl::OUString *pElements = aElements.empty() ? 0 : &aElements[0];
2135 			aList = Sequence< ::rtl::OUString >(pElements, aElements.size());
2136 		}
2137 		else
2138 		{
2139 			OSL_ENSURE(sal_False, "OFormImport::implTranslateStringListProperty: invalid value (empty)!");
2140 		}
2141 
2142 		aProp.Value <<= aList;
2143 
2144 		// add the property to the base class' array
2145 		implPushBackPropertyValue(aProp);
2146 	}
2147 	//=====================================================================
2148 	//= OXMLDataSourceImport
2149 	//=====================================================================
2150 	OXMLDataSourceImport::OXMLDataSourceImport(
2151 					SvXMLImport& _rImport
2152 					,sal_uInt16 nPrfx
2153 					, const ::rtl::OUString& _sLocalName
2154 					,const Reference< ::com::sun::star::xml::sax::XAttributeList > & _xAttrList
2155 					,const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xElement) :
2156 		SvXMLImportContext( _rImport, nPrfx, _sLocalName )
2157 	{
2158 		OSL_ENSURE(_xAttrList.is(),"Attribute list is NULL!");
2159         const SvXMLNamespaceMap& rMap = _rImport.GetNamespaceMap();
2160 
2161 		sal_Int16 nLength = (_xElement.is() && _xAttrList.is()) ? _xAttrList->getLength() : 0;
2162 		for(sal_Int16 i = 0; i < nLength; ++i)
2163 		{
2164 			::rtl::OUString sLocalName;
2165 			::rtl::OUString sAttrName = _xAttrList->getNameByIndex( i );
2166             sal_uInt16 nPrefix = rMap.GetKeyByAttrName( sAttrName, &sLocalName );
2167 
2168 			if  (   ( nPrefix == OAttributeMetaData::getCommonControlAttributeNamespace( CCA_TARGET_LOCATION ) )
2169                 &&  ( sLocalName.equalsAscii( OAttributeMetaData::getCommonControlAttributeName( CCA_TARGET_LOCATION ) ) )
2170                 )
2171 			{
2172                 ::rtl::OUString sValue = _xAttrList->getValueByIndex( i );
2173 
2174 				INetURLObject aURL(sValue);
2175 				if ( aURL.GetProtocol() == INET_PROT_FILE )
2176 					_xElement->setPropertyValue(PROPERTY_DATASOURCENAME,makeAny(sValue));
2177 				else
2178 					_xElement->setPropertyValue(PROPERTY_URL,makeAny(sValue)); // the url is the "sdbc:" string
2179 				break;
2180 			}
2181 		}
2182 	}
2183 	//---------------------------------------------------------------------
2184 	OControlImport* OFormImport::implCreateChildContext(
2185 			sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
2186 			OControlElement::ElementType _eType )
2187 	{
2188 		switch (_eType)
2189 		{
2190 			case OControlElement::TEXT:
2191 			case OControlElement::TEXT_AREA:
2192 			case OControlElement::FORMATTED_TEXT:
2193 				return new OTextLikeImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2194 
2195 			case OControlElement::BUTTON:
2196 			case OControlElement::IMAGE:
2197 			case OControlElement::IMAGE_FRAME:
2198 				return new OButtonImport( m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType );
2199 
2200 			case OControlElement::COMBOBOX:
2201 			case OControlElement::LISTBOX:
2202 				return new OListAndComboImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2203 
2204 			case OControlElement::RADIO:
2205 				return new ORadioImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2206 
2207             case OControlElement::CHECKBOX:
2208 				return new OImagePositionImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2209 
2210 			case OControlElement::PASSWORD:
2211 				return new OPasswordImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2212 
2213 			case OControlElement::FRAME:
2214 			case OControlElement::FIXED_TEXT:
2215 				return new OReferredControlImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2216 
2217 			case OControlElement::GRID:
2218 				return new OGridImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2219 
2220             case OControlElement::VALUERANGE:
2221                 return new OValueRangeImport( m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType );
2222 
2223 			default:
2224 				return new OControlImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2225 		}
2226 	}
2227 
2228 //.........................................................................
2229 }	// namespace xmloff
2230 //.........................................................................
2231 
2232