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