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             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::TIME:              pServiceName = "com.sun.star.form.component.DateField"; break;
716         case OControlElement::DATE:              pServiceName = "com.sun.star.form.component.TimeField"; break;
717         default:                                 break;
718         }
719         if ( pServiceName != NULL )
720             return ::rtl::OUString::createFromAscii( pServiceName );
721         return ::rtl::OUString();
722     }
723 
724 	//---------------------------------------------------------------------
725 	void OControlImport::addOuterAttributes(const Reference< sax::XAttributeList >& _rxOuterAttribs)
726 	{
727 		OSL_ENSURE(!m_xOuterAttributes.is(), "OControlImport::addOuterAttributes: already have these attributes!");
728 		m_xOuterAttributes = _rxOuterAttribs;
729 	}
730 
731 	//---------------------------------------------------------------------
732 	bool OControlImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
733 	{
734 		static const sal_Char* pLinkedCellAttributeName = OAttributeMetaData::getBindingAttributeName(BA_LINKED_CELL);
735 
736         if (IsXMLToken(_rLocalName, XML_ID))
737         {   // it's the control id
738             if (XML_NAMESPACE_XML == _nNamespaceKey)
739             {
740                 m_sControlId = _rValue;
741             }
742             else if (XML_NAMESPACE_FORM == _nNamespaceKey)
743             {
744                 if (!m_sControlId.getLength())
745                 {
746                     m_sControlId = _rValue;
747                 }
748             }
749             return true;
750         }
751 
752         if ( _rLocalName.equalsAscii( pLinkedCellAttributeName ) )
753         {   // it's the address of a spreadsheet cell
754             m_sBoundCellAddress = _rValue;
755             return true;
756         }
757 
758         if ( _nNamespaceKey == XML_NAMESPACE_XFORMS && IsXMLToken( _rLocalName, XML_BIND ) )
759         {
760             m_sBindingID = _rValue;
761             return true;
762         }
763 
764         if ( _nNamespaceKey == XML_NAMESPACE_FORM && IsXMLToken( _rLocalName, XML_XFORMS_LIST_SOURCE )  )
765         {
766             m_sListBindingID = _rValue;
767             return true;
768         }
769 
770         if  (   (   ( _nNamespaceKey == XML_NAMESPACE_FORM )
771                 &&  IsXMLToken( _rLocalName, XML_XFORMS_SUBMISSION )
772                 )
773             ||  (   ( _nNamespaceKey == XML_NAMESPACE_XFORMS )
774                 &&  IsXMLToken( _rLocalName, XML_SUBMISSION )
775                 )
776             )
777         {
778             m_sSubmissionID = _rValue;
779             return true;
780         }
781 
782         if ( OElementImport::tryGenericAttribute( _nNamespaceKey, _rLocalName, _rValue ) )
783             return true;
784 
785 		static const sal_Char* pValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_VALUE);
786 		static const sal_Char* pCurrentValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_VALUE);
787         static const sal_Char* pMinValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCA_MIN_VALUE);
788 		static const sal_Char* pMaxValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCA_MAX_VALUE);
789         static const sal_Char* pRepeatDelayAttributeName = OAttributeMetaData::getSpecialAttributeName( SCA_REPEAT_DELAY );
790 
791 		sal_Int32 nHandle = -1;
792         if ( _rLocalName.equalsAscii( pValueAttributeName ) )
793             nHandle = PROPID_VALUE;
794         else if ( _rLocalName.equalsAscii( pCurrentValueAttributeName ) )
795             nHandle = PROPID_CURRENT_VALUE;
796         else if ( _rLocalName.equalsAscii( pMinValueAttributeName ) )
797             nHandle = PROPID_MIN_VALUE;
798         else if ( _rLocalName.equalsAscii( pMaxValueAttributeName ) )
799             nHandle = PROPID_MAX_VALUE;
800         if ( nHandle != -1 )
801 		{
802 			// for the moment, simply remember the name and the value
803 			PropertyValue aProp;
804 			aProp.Name = _rLocalName;
805 			aProp.Handle = nHandle;
806 			aProp.Value <<= _rValue;
807 			m_aValueProperties.push_back(aProp);
808             return true;
809 		}
810 
811 		if ( _rLocalName.equalsAscii( pRepeatDelayAttributeName ) )
812         {
813             ::Time aTime;
814             sal_Int32 nFractions = 0;
815             if ( SvXMLUnitConverter::convertTimeDuration( _rValue, aTime, &nFractions ) )
816             {
817 			    PropertyValue aProp;
818 			    aProp.Name = PROPERTY_REPEAT_DELAY;
819 			    aProp.Value <<= (sal_Int32)( ( ( aTime.GetMSFromTime() / 1000 ) * 1000 ) + nFractions );
820 
821 			    implPushBackPropertyValue(aProp);
822             }
823             return true;
824         }
825 
826 		return OElementImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue );
827 	}
828 
829 	//---------------------------------------------------------------------
830 	void OControlImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
831 	{
832 		::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > xAttributes;
833 		if( m_xOuterAttributes.is() )
834 		{
835 			// merge the attribute lists
836 			OAttribListMerger* pMerger = new OAttribListMerger;
837 			// our own one
838 			pMerger->addList(_rxAttrList);
839 			// and the ones of our enclosing element
840 			pMerger->addList(m_xOuterAttributes);
841 			xAttributes = pMerger;
842 		}
843 		else
844 		{
845 			xAttributes = _rxAttrList;
846 		}
847 
848 		// let the base class handle all the attributes
849 		OElementImport::StartElement(xAttributes);
850 
851 		if ( !m_aValueProperties.empty() && m_xElement.is())
852 		{
853 			// get the property set info
854 			if (!m_xInfo.is())
855 			{
856 				OSL_ENSURE(sal_False, "OControlImport::StartElement: no PropertySetInfo!");
857 				return;
858 			}
859 
860 			const sal_Char* pValueProperty = NULL;
861 			const sal_Char* pCurrentValueProperty = NULL;
862 			const sal_Char* pMinValueProperty = NULL;
863 			const sal_Char* pMaxValueProperty = NULL;
864 
865 			sal_Bool bRetrievedValues = sal_False;
866 			sal_Bool bRetrievedValueLimits = sal_False;
867 
868 			// get the class id of our element
869 			sal_Int16 nClassId = FormComponentType::CONTROL;
870 			m_xElement->getPropertyValue(PROPERTY_CLASSID) >>= nClassId;
871 
872 			// translate the value properties we collected in handleAttributes
873             PropertyValueArray::iterator aEnd = m_aValueProperties.end();
874             for	(	PropertyValueArray::iterator aValueProps = m_aValueProperties.begin();
875 					aValueProps != aEnd;
876 					++aValueProps
877 				)
878 			{
879                 bool bSuccess = false;
880 				switch (aValueProps->Handle)
881 				{
882 					case PROPID_VALUE:
883 					case PROPID_CURRENT_VALUE:
884 					{
885 						// get the property names
886 						if (!bRetrievedValues)
887 						{
888 							getValuePropertyNames(m_eElementType, nClassId, pCurrentValueProperty, pValueProperty);
889                             ENSURE_OR_BREAK( pValueProperty, "OControlImport::StartElement: illegal value property names!" );
890 							bRetrievedValues = sal_True;
891 						}
892 						ENSURE_OR_BREAK((PROPID_VALUE != aValueProps->Handle) || pValueProperty,
893 							"OControlImport::StartElement: the control does not have a value property!");
894 						ENSURE_OR_BREAK((PROPID_CURRENT_VALUE != aValueProps->Handle) || pCurrentValueProperty,
895 							"OControlImport::StartElement: the control does not have a current-value property!");
896 
897 						// transfer the name
898 						if (PROPID_VALUE == aValueProps->Handle)
899 							aValueProps->Name = ::rtl::OUString::createFromAscii(pValueProperty);
900 						else
901 							aValueProps->Name = ::rtl::OUString::createFromAscii(pCurrentValueProperty);
902                         bSuccess = true;
903 					}
904 					break;
905 					case PROPID_MIN_VALUE:
906 					case PROPID_MAX_VALUE:
907 					{
908 						// get the property names
909 						if (!bRetrievedValueLimits)
910 						{
911 							getValueLimitPropertyNames(nClassId, pMinValueProperty, pMaxValueProperty);
912                             ENSURE_OR_BREAK( pMinValueProperty && pMaxValueProperty, "OControlImport::StartElement: illegal value limit property names!" );
913 							bRetrievedValueLimits = sal_True;
914 						}
915 						OSL_ENSURE((PROPID_MIN_VALUE != aValueProps->Handle) || pMinValueProperty,
916 							"OControlImport::StartElement: the control does not have a value property!");
917 						OSL_ENSURE((PROPID_MAX_VALUE != aValueProps->Handle) || pMaxValueProperty,
918 							"OControlImport::StartElement: the control does not have a current-value property!");
919 
920 						// transfer the name
921 						if (PROPID_MIN_VALUE == aValueProps->Handle)
922 							aValueProps->Name = ::rtl::OUString::createFromAscii(pMinValueProperty);
923 						else
924 							aValueProps->Name = ::rtl::OUString::createFromAscii(pMaxValueProperty);
925                         bSuccess = true;
926 					}
927 					break;
928 				}
929 
930                 if ( !bSuccess )
931                     continue;
932 
933 				// translate the value
934 				implTranslateValueProperty(m_xInfo, *aValueProps);
935 				// add the property to the base class' array
936 				implPushBackPropertyValue(*aValueProps);
937 			}
938 		}
939 	}
940 
941 	//---------------------------------------------------------------------
942 	void OControlImport::implTranslateValueProperty(const Reference< XPropertySetInfo >& _rxPropInfo,
943 		PropertyValue& _rPropValue)
944 	{
945 		OSL_ENSURE(_rxPropInfo->hasPropertyByName(_rPropValue.Name),
946 			"OControlImport::implTranslateValueProperty: invalid property name!");
947 
948 		// retrieve the type of the property
949 		Property aProp = _rxPropInfo->getPropertyByName(_rPropValue.Name);
950 		// the untranslated string value as read in handleAttribute
951 		::rtl::OUString sValue;
952     #if OSL_DEBUG_LEVEL > 0
953 		sal_Bool bSuccess =
954 	#endif
955 		_rPropValue.Value >>= sValue;
956 		OSL_ENSURE(bSuccess, "OControlImport::implTranslateValueProperty: supposed to be called with non-translated string values!");
957 
958 		if (TypeClass_ANY == aProp.Type.getTypeClass())
959 		{
960 			// we have exactly 2 properties where this type class is allowed:
961 			OSL_ENSURE(
962 					(0 == _rPropValue.Name.compareToAscii(PROPERTY_EFFECTIVE_VALUE))
963 				||	(0 == _rPropValue.Name.compareToAscii(PROPERTY_EFFECTIVE_DEFAULT)),
964 				"OControlImport::implTranslateValueProperty: invalid property type/name combination!");
965 
966 			// Both properties are allowed to have a double or a string value,
967 			// so first try to convert the string into a number
968 			double nValue;
969 			if (GetImport().GetMM100UnitConverter().convertDouble(nValue, sValue))
970 				_rPropValue.Value <<= nValue;
971 			else
972 				_rPropValue.Value <<= sValue;
973 		}
974 		else
975 			_rPropValue.Value = PropertyConversion::convertString(GetImport(), aProp.Type, sValue);
976 	}
977 
978 	//---------------------------------------------------------------------
979 	void OControlImport::EndElement()
980 	{
981 		OSL_ENSURE(m_xElement.is(), "OControlImport::EndElement: invalid control!");
982 		if ( !m_xElement.is() )
983 			return;
984 
985 		// register our control with it's id
986 		if (m_sControlId.getLength())
987 			m_rFormImport.registerControlId(m_xElement, m_sControlId);
988 		// it's allowed to have no control id. In this case we're importing a column
989 
990 		// one more pre-work to do:
991 		// when we set default values, then by definition the respective value is set
992 		// to this default value, too. This means if the sequence contains for example
993 		// a DefaultText value, then the Text will be affected by this, too.
994 		// In case the Text is not part of the property sequence (or occurs _before_
995 		// the DefaultText, which can happen for other value/default-value property names),
996 		// this means that the Text (the value property) is incorrectly imported.
997 		// #102475# - 04.09.2002 - fs@openoffice.org
998 
999 		sal_Bool bRestoreValuePropertyValue = sal_False;
1000 		Any aValuePropertyValue;
1001 
1002 		sal_Int16 nClassId = FormComponentType::CONTROL;
1003 		try
1004 		{
1005 			// get the class id of our element
1006 			m_xElement->getPropertyValue(PROPERTY_CLASSID) >>= nClassId;
1007 		}
1008 		catch( const Exception& )
1009 		{
1010 			OSL_ENSURE( sal_False, "OControlImport::EndElement: caught an exception while retrieving the class id!" );
1011 		}
1012 
1013 		const sal_Char* pValueProperty = NULL;
1014 		const sal_Char* pDefaultValueProperty = NULL;
1015 		getRuntimeValuePropertyNames(m_eElementType, nClassId, pValueProperty, pDefaultValueProperty);
1016 		if ( pDefaultValueProperty && pValueProperty )
1017 		{
1018 			sal_Bool bNonDefaultValuePropertyValue = sal_False;
1019 				// is the "value property" part of the sequence?
1020 
1021 			// look up this property in our sequence
1022             PropertyValueArray::iterator aEnd = m_aValues.end();
1023 			for (	PropertyValueArray::iterator aCheck = m_aValues.begin();
1024 					( aCheck != aEnd );
1025 					++aCheck
1026 				)
1027 			{
1028 				if ( aCheck->Name.equalsAscii( pDefaultValueProperty ) )
1029 					bRestoreValuePropertyValue = sal_True;
1030 				else if ( aCheck->Name.equalsAscii( pValueProperty ) )
1031 				{
1032 					bNonDefaultValuePropertyValue = sal_True;
1033 					// we need to restore the value property we found here, nothing else
1034 					aValuePropertyValue = aCheck->Value;
1035 				}
1036 			}
1037 
1038 			if ( bRestoreValuePropertyValue && !bNonDefaultValuePropertyValue )
1039 			{
1040 				// found it -> need to remember (and restore) the "value property value", which is not set explicitly
1041 				try
1042 				{
1043 					aValuePropertyValue = m_xElement->getPropertyValue( ::rtl::OUString::createFromAscii( pValueProperty ) );
1044 				}
1045 				catch( const Exception& )
1046 				{
1047 					OSL_ENSURE( sal_False, "OControlImport::EndElement: caught an exception while retrieving the current value property!" );
1048 				}
1049 			}
1050 		}
1051 
1052 		// let the base class set all the values
1053 		OElementImport::EndElement();
1054 
1055 		// restore the "value property value", if necessary
1056 		if ( bRestoreValuePropertyValue && pValueProperty )
1057 		{
1058 			try
1059 			{
1060 				m_xElement->setPropertyValue( ::rtl::OUString::createFromAscii( pValueProperty ), aValuePropertyValue );
1061 			}
1062 			catch( const Exception& )
1063 			{
1064 				OSL_ENSURE( sal_False, "OControlImport::EndElement: caught an exception while restoring the value property!" );
1065 			}
1066 		}
1067 
1068         // the external cell binding, if applicable
1069         if ( m_xElement.is() && m_sBoundCellAddress.getLength() )
1070             doRegisterCellValueBinding( m_sBoundCellAddress );
1071 
1072         // XForms binding, if applicable
1073         if ( m_xElement.is() && m_sBindingID.getLength() )
1074             doRegisterXFormsValueBinding( m_sBindingID );
1075 
1076         // XForms list binding, if applicable
1077         if ( m_xElement.is() && m_sListBindingID.getLength() )
1078             doRegisterXFormsListBinding( m_sListBindingID );
1079 
1080         // XForms submission, if applicable
1081         if ( m_xElement.is() && m_sSubmissionID.getLength() )
1082             doRegisterXFormsSubmission( m_sSubmissionID );
1083 	}
1084 
1085 	//---------------------------------------------------------------------
1086     void OControlImport::doRegisterCellValueBinding( const ::rtl::OUString& _rBoundCellAddress )
1087     {
1088         OSL_PRECOND( m_xElement.is(), "OControlImport::doRegisterCellValueBinding: invalid element!" );
1089         OSL_PRECOND( _rBoundCellAddress.getLength(),
1090             "OControlImport::doRegisterCellValueBinding: invalid address!" );
1091 
1092         m_rContext.registerCellValueBinding( m_xElement, _rBoundCellAddress );
1093     }
1094 
1095     //---------------------------------------------------------------------
1096     void OControlImport::doRegisterXFormsValueBinding( const ::rtl::OUString& _rBindingID )
1097     {
1098         OSL_PRECOND( m_xElement.is(), "need element" );
1099         OSL_PRECOND( _rBindingID.getLength() > 0, "binding ID is not valid" );
1100 
1101         m_rContext.registerXFormsValueBinding( m_xElement, _rBindingID );
1102     }
1103 
1104     //---------------------------------------------------------------------
1105     void OControlImport::doRegisterXFormsListBinding( const ::rtl::OUString& _rBindingID )
1106     {
1107         OSL_PRECOND( m_xElement.is(), "need element" );
1108         OSL_PRECOND( _rBindingID.getLength() > 0, "binding ID is not valid" );
1109 
1110         m_rContext.registerXFormsListBinding( m_xElement, _rBindingID );
1111     }
1112 
1113     //---------------------------------------------------------------------
1114     void OControlImport::doRegisterXFormsSubmission( const ::rtl::OUString& _rSubmissionID )
1115     {
1116         OSL_PRECOND( m_xElement.is(), "need element" );
1117         OSL_PRECOND( _rSubmissionID.getLength() > 0, "binding ID is not valid" );
1118 
1119         m_rContext.registerXFormsSubmission( m_xElement, _rSubmissionID );
1120     }
1121 
1122     //---------------------------------------------------------------------
1123 	//added by BerryJia for fixing bug102407 2002-11-5
1124 	Reference< XPropertySet > OControlImport::createElement()
1125 	{
1126 		const Reference<XPropertySet> xPropSet = OElementImport::createElement();
1127 		if ( xPropSet.is() )
1128 		{
1129             m_xInfo = xPropSet->getPropertySetInfo();
1130 			if ( m_xInfo.is() && m_xInfo->hasPropertyByName(PROPERTY_ALIGN) )
1131 			{
1132 				Any aValue;
1133 				xPropSet->setPropertyValue(PROPERTY_ALIGN,aValue);
1134 			}
1135 		}
1136 		return xPropSet;
1137 	}
1138 
1139 	//=====================================================================
1140 	//= OImagePositionImport
1141 	//=====================================================================
1142 	//---------------------------------------------------------------------
1143     OImagePositionImport::OImagePositionImport( OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager,
1144         sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, const Reference< XNameContainer >& _rxParentContainer,
1145 		OControlElement::ElementType _eType )
1146         :OControlImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType )
1147         ,m_nImagePosition( -1 )
1148         ,m_nImageAlign( 0 )
1149         ,m_bHaveImagePosition( sal_False )
1150     {
1151     }
1152 
1153 	//---------------------------------------------------------------------
1154     bool OImagePositionImport::handleAttribute( sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName,
1155         const ::rtl::OUString& _rValue )
1156     {
1157         if ( _rLocalName == GetXMLToken( XML_IMAGE_POSITION ) )
1158         {
1159             OSL_VERIFY( PropertyConversion::convertString(
1160                 m_rContext.getGlobalContext(), ::getCppuType( &m_nImagePosition ),
1161                 _rValue, OEnumMapper::getEnumMap( OEnumMapper::epImagePosition )
1162             ) >>= m_nImagePosition );
1163             m_bHaveImagePosition = sal_True;
1164             return true;
1165         }
1166 
1167         if ( _rLocalName == GetXMLToken( XML_IMAGE_ALIGN ) )
1168         {
1169             OSL_VERIFY( PropertyConversion::convertString(
1170                 m_rContext.getGlobalContext(), ::getCppuType( &m_nImageAlign ),
1171                 _rValue, OEnumMapper::getEnumMap( OEnumMapper::epImageAlign )
1172             ) >>= m_nImageAlign );
1173             return true;
1174         }
1175 
1176         return OControlImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue );
1177     }
1178 
1179 	//---------------------------------------------------------------------
1180 	void OImagePositionImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1181 	{
1182 		OControlImport::StartElement( _rxAttrList );
1183 
1184         if ( m_bHaveImagePosition )
1185         {
1186             sal_Int16 nUnoImagePosition = ImagePosition::Centered;
1187             if ( m_nImagePosition >= 0 )
1188             {
1189                 OSL_ENSURE( ( m_nImagePosition <= 3 ) && ( m_nImageAlign >= 0 ) && ( m_nImageAlign < 3 ),
1190                     "OImagePositionImport::StartElement: unknown image align and/or position!" );
1191                 nUnoImagePosition = m_nImagePosition * 3 + m_nImageAlign;
1192             }
1193 
1194             PropertyValue aImagePosition;
1195 		    aImagePosition.Name = PROPERTY_IMAGE_POSITION;
1196 		    aImagePosition.Value <<= nUnoImagePosition;
1197 		    implPushBackPropertyValue( aImagePosition );
1198         }
1199 	}
1200 
1201     //=====================================================================
1202 	//= OReferredControlImport
1203 	//=====================================================================
1204 	//---------------------------------------------------------------------
1205 	OReferredControlImport::OReferredControlImport(
1206 			OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1207 			const Reference< XNameContainer >& _rxParentContainer,
1208 			OControlElement::ElementType )
1209 		:OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer)
1210 	{
1211 	}
1212 
1213 	//---------------------------------------------------------------------
1214 	void OReferredControlImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1215 	{
1216 		OControlImport::StartElement(_rxAttrList);
1217 
1218 		// the base class should have created the control, so we can register it
1219 		if ( m_sReferringControls.getLength() )
1220 			m_rFormImport.registerControlReferences(m_xElement, m_sReferringControls);
1221 	}
1222 
1223 	//---------------------------------------------------------------------
1224 	bool OReferredControlImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName,
1225 		const ::rtl::OUString& _rValue)
1226 	{
1227 		static const ::rtl::OUString s_sReferenceAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_FOR));
1228 		if (_rLocalName == s_sReferenceAttributeName)
1229         {
1230 			m_sReferringControls = _rValue;
1231             return true;
1232         }
1233 		return OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue);
1234 	}
1235 
1236 	//=====================================================================
1237 	//= OPasswordImport
1238 	//=====================================================================
1239 	//---------------------------------------------------------------------
1240 	OPasswordImport::OPasswordImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1241 			const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType)
1242 		:OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType)
1243 	{
1244 	}
1245 
1246 	//---------------------------------------------------------------------
1247 	bool OPasswordImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
1248 	{
1249 		static const ::rtl::OUString s_sEchoCharAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getSpecialAttributeName(SCA_ECHO_CHAR));
1250 		if (_rLocalName == s_sEchoCharAttributeName)
1251 		{
1252 			// need a special handling for the EchoChar property
1253 			PropertyValue aEchoChar;
1254 			aEchoChar.Name = PROPERTY_ECHOCHAR;
1255 			OSL_ENSURE(_rValue.getLength() == 1, "OPasswordImport::handleAttribute: invalid echo char attribute!");
1256 				// we ourself should not have written values other than of length 1
1257 			if (_rValue.getLength() >= 1)
1258 				aEchoChar.Value <<= (sal_Int16)_rValue.getStr()[0];
1259 			else
1260 				aEchoChar.Value <<= (sal_Int16)0;
1261 			implPushBackPropertyValue(aEchoChar);
1262             return true;
1263 		}
1264 		return OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue);
1265 	}
1266 
1267 	//=====================================================================
1268 	//= ORadioImport
1269 	//=====================================================================
1270 	//---------------------------------------------------------------------
1271 	ORadioImport::ORadioImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1272 			const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType)
1273 		:OImagePositionImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType )
1274 	{
1275 	}
1276 
1277 	//---------------------------------------------------------------------
1278 	bool ORadioImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
1279 	{
1280 		// need special handling for the State & CurrentState properties:
1281 		// they're stored as booleans, but expected to be int16 properties
1282         static const sal_Char* pCurrentSelectedAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_SELECTED);
1283 		static const sal_Char* pSelectedAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCA_SELECTED);
1284 		if  (  _rLocalName.equalsAscii( pCurrentSelectedAttributeName )
1285             || _rLocalName.equalsAscii( pSelectedAttributeName )
1286             )
1287 		{
1288 			const OAttribute2Property::AttributeAssignment* pProperty = m_rContext.getAttributeMap().getAttributeTranslation(_rLocalName);
1289 			OSL_ENSURE(pProperty, "ORadioImport::handleAttribute: invalid property map!");
1290 			if (pProperty)
1291 			{
1292 				const Any aBooleanValue( PropertyConversion::convertString(m_rContext.getGlobalContext(), pProperty->aPropertyType, _rValue, pProperty->pEnumMap) );
1293 
1294 				// create and store a new PropertyValue
1295 				PropertyValue aNewValue;
1296 				aNewValue.Name = pProperty->sPropertyName;
1297 				aNewValue.Value <<= (sal_Int16)::cppu::any2bool(aBooleanValue);
1298 
1299 				implPushBackPropertyValue(aNewValue);
1300 			}
1301             return true;
1302 		}
1303 		return OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue );
1304 	}
1305 
1306 	//=====================================================================
1307 	//= OURLReferenceImport
1308 	//=====================================================================
1309 	OURLReferenceImport::OURLReferenceImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1310 			const Reference< XNameContainer >& _rxParentContainer,
1311 			OControlElement::ElementType _eType)
1312 		:OImagePositionImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType)
1313 	{
1314 	}
1315 
1316 	//---------------------------------------------------------------------
1317 	bool OURLReferenceImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
1318 	{
1319 		static const sal_Char* s_pTargetLocationAttributeName	= OAttributeMetaData::getCommonControlAttributeName( CCA_TARGET_LOCATION );
1320 		static const sal_Char* s_pImageDataAttributeName		= OAttributeMetaData::getCommonControlAttributeName( CCA_IMAGE_DATA );
1321 
1322 		// need to make the URL absolute if
1323 		// * it's the image-data attribute
1324 		// * it's the target-location attribute, and we're dealign with an object which has the respective property
1325 		sal_Bool bMakeAbsolute =
1326 				( 0 == _rLocalName.compareToAscii( s_pImageDataAttributeName ) )
1327 			||	(	( 0 == _rLocalName.compareToAscii( s_pTargetLocationAttributeName ) )
1328 				&&	(	( OControlElement::BUTTON == m_eElementType )
1329 					||	( OControlElement::IMAGE == m_eElementType )
1330 					)
1331 				);
1332 
1333 		if ( bMakeAbsolute && ( _rValue.getLength() > 0  ) )
1334 		{
1335 			// make a global URL out of the local one
1336             ::rtl::OUString sAdjustedValue;
1337             // only resolve image related url
1338             // we don't want say form url targets to be resolved
1339             // using ResolveGraphicObjectURL
1340             if ( 0 == _rLocalName.compareToAscii( s_pImageDataAttributeName ) )
1341                 sAdjustedValue = m_rContext.getGlobalContext().ResolveGraphicObjectURL( _rValue, sal_False );
1342             else
1343                 sAdjustedValue = m_rContext.getGlobalContext().GetAbsoluteReference( _rValue );
1344             return OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, sAdjustedValue );
1345 		}
1346 
1347 		return OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue );
1348 	}
1349 
1350 	//=====================================================================
1351 	//= OButtonImport
1352 	//=====================================================================
1353 	//---------------------------------------------------------------------
1354 	OButtonImport::OButtonImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1355 			const Reference< XNameContainer >& _rxParentContainer,
1356 			OControlElement::ElementType _eType)
1357 		:OURLReferenceImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType)
1358 	{
1359 		enableTrackAttributes();
1360 	}
1361 
1362 	//---------------------------------------------------------------------
1363 	void OButtonImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1364 	{
1365 		OURLReferenceImport::StartElement(_rxAttrList);
1366 
1367 		// handle the target-frame attribute
1368 		simulateDefaultedAttribute(OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_FRAME), PROPERTY_TARGETFRAME, "_blank");
1369 	}
1370 
1371 	//=====================================================================
1372 	//= OValueRangeImport
1373 	//=====================================================================
1374 	//---------------------------------------------------------------------
1375 	OValueRangeImport::OValueRangeImport( OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1376 			const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType )
1377 		:OControlImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType )
1378         ,m_nStepSizeValue( 1 )
1379 	{
1380 
1381 	}
1382 
1383 	//---------------------------------------------------------------------
1384 	bool OValueRangeImport::handleAttribute( sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue )
1385     {
1386         if ( _rLocalName.equalsAscii( OAttributeMetaData::getSpecialAttributeName( SCA_STEP_SIZE ) ) )
1387         {
1388     		GetImport().GetMM100UnitConverter().convertNumber( m_nStepSizeValue, _rValue );
1389             return true;
1390         }
1391         return OControlImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue );
1392     }
1393 
1394 	//---------------------------------------------------------------------
1395 	void OValueRangeImport::StartElement( const Reference< sax::XAttributeList >& _rxAttrList )
1396 	{
1397 		OControlImport::StartElement( _rxAttrList );
1398 
1399         if ( m_xInfo.is() )
1400         {
1401             if ( m_xInfo->hasPropertyByName( PROPERTY_SPIN_INCREMENT ) )
1402                 m_xElement->setPropertyValue( PROPERTY_SPIN_INCREMENT, makeAny( m_nStepSizeValue ) );
1403             else if ( m_xInfo->hasPropertyByName( PROPERTY_LINE_INCREMENT ) )
1404                 m_xElement->setPropertyValue( PROPERTY_LINE_INCREMENT, makeAny( m_nStepSizeValue ) );
1405 		}
1406 	}
1407 
1408 	//=====================================================================
1409 	//= OTextLikeImport
1410 	//=====================================================================
1411 	//---------------------------------------------------------------------
1412 	OTextLikeImport::OTextLikeImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1413 			const Reference< XNameContainer >& _rxParentContainer,
1414 			OControlElement::ElementType _eType)
1415 		:OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType)
1416         ,m_bEncounteredTextPara( false )
1417 	{
1418 		enableTrackAttributes();
1419 	}
1420 
1421 	//---------------------------------------------------------------------
1422     SvXMLImportContext* OTextLikeImport::CreateChildContext( sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
1423         const Reference< sax::XAttributeList >& _rxAttrList )
1424     {
1425 		if ( ( XML_NAMESPACE_TEXT == _nPrefix ) && _rLocalName.equalsIgnoreAsciiCaseAscii( "p" ) )
1426         {
1427             OSL_ENSURE( m_eElementType == OControlElement::TEXT_AREA,
1428                 "OTextLikeImport::CreateChildContext: text paragraphs in a non-text-area?" );
1429 
1430             if ( m_eElementType == OControlElement::TEXT_AREA )
1431             {
1432                 Reference< XText > xTextElement( m_xElement, UNO_QUERY );
1433                 if ( xTextElement.is() )
1434                 {
1435                     UniReference < XMLTextImportHelper > xTextImportHelper( m_rContext.getGlobalContext().GetTextImport() );
1436 
1437                     if ( !m_xCursor.is() )
1438                     {
1439 				        m_xOldCursor = xTextImportHelper->GetCursor();
1440 				        m_xCursor = xTextElement->createTextCursor();
1441 
1442                         if ( m_xCursor.is() )
1443 					        xTextImportHelper->SetCursor( m_xCursor );
1444                     }
1445                     if ( m_xCursor.is() )
1446                     {
1447                         m_bEncounteredTextPara = true;
1448 			            return xTextImportHelper->CreateTextChildContext( m_rContext.getGlobalContext(), _nPrefix, _rLocalName, _rxAttrList );
1449                     }
1450                 }
1451                 else
1452                 {
1453                     // in theory, we could accumulate all the text portions (without formatting),
1454                     // and set it as Text property at the model ...
1455                 }
1456             }
1457         }
1458 
1459         return OControlImport::CreateChildContext( _nPrefix, _rLocalName, _rxAttrList );
1460     }
1461 
1462 	//---------------------------------------------------------------------
1463 	void OTextLikeImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1464 	{
1465 		OControlImport::StartElement(_rxAttrList);
1466 
1467 		// handle the convert-empty-to-null attribute, whose default is different from the property default
1468 		// unfortunately, different classes are imported by this class ('cause they're represented by the
1469 		// same XML element), though not all of them know this property.
1470 		// So we have to do a check ...
1471 		if (m_xElement.is() && m_xInfo.is() && m_xInfo->hasPropertyByName(PROPERTY_EMPTY_IS_NULL) )
1472 			simulateDefaultedAttribute(OAttributeMetaData::getDatabaseAttributeName(DA_CONVERT_EMPTY), PROPERTY_EMPTY_IS_NULL, "false");
1473 	}
1474 
1475 	//---------------------------------------------------------------------
1476     struct EqualHandle : public ::std::unary_function< PropertyValue, bool >
1477     {
1478         const sal_Int32 m_nHandle;
1479         EqualHandle( sal_Int32 _nHandle ) : m_nHandle( _nHandle ) { }
1480 
1481         inline bool operator()( const PropertyValue& _rProp )
1482         {
1483             return _rProp.Handle == m_nHandle;
1484         }
1485     };
1486 
1487 	//---------------------------------------------------------------------
1488 	void OTextLikeImport::removeRedundantCurrentValue()
1489     {
1490         if ( m_bEncounteredTextPara )
1491         {
1492             // In case the text is written in the text:p elements, we need to ignore what we read as
1493             // current-value attribute, since it's redundant.
1494             // fortunately, OElementImport tagged the value property with the PROPID_CURRENT_VALUE
1495             // handle, so we do not need to determine the name of our value property here
1496             // (normally, it should be "Text", since no other controls than the edit field should
1497             // have the text:p elements)
1498             PropertyValueArray::iterator aValuePropertyPos = ::std::find_if(
1499                 m_aValues.begin(),
1500                 m_aValues.end(),
1501                 EqualHandle( PROPID_CURRENT_VALUE )
1502             );
1503             if ( aValuePropertyPos != m_aValues.end() )
1504             {
1505                 OSL_ENSURE( aValuePropertyPos->Name == PROPERTY_TEXT, "OTextLikeImport::EndElement: text:p was present, but our value property is *not* 'Text'!" );
1506                 if ( aValuePropertyPos->Name == PROPERTY_TEXT )
1507                 {
1508                     ::std::copy(
1509                         aValuePropertyPos + 1,
1510                         m_aValues.end(),
1511                         aValuePropertyPos
1512                     );
1513                     m_aValues.resize( m_aValues.size() - 1 );
1514                 }
1515             }
1516 
1517             // additionally, we need to set the "RichText" property of our element to sal_True
1518             // (the presence of the text:p is used as indicator for the value of the RichText property)
1519             sal_Bool bHasRichTextProperty = sal_False;
1520 			if ( m_xInfo.is() )
1521 				bHasRichTextProperty = m_xInfo->hasPropertyByName( PROPERTY_RICH_TEXT );
1522             OSL_ENSURE( bHasRichTextProperty, "OTextLikeImport::EndElement: text:p, but no rich text control?" );
1523             if ( bHasRichTextProperty )
1524                 m_xElement->setPropertyValue( PROPERTY_RICH_TEXT, makeAny( (sal_Bool)sal_True ) );
1525         }
1526         // Note that we do *not* set the RichText property (in case our element has one) to sal_False here
1527         // since this is the default of this property, anyway.
1528     }
1529 
1530 	//---------------------------------------------------------------------
1531     struct EqualName : public ::std::unary_function< PropertyValue, bool >
1532     {
1533         const ::rtl::OUString m_sName;
1534         EqualName( const ::rtl::OUString& _rName ) : m_sName( _rName ) { }
1535 
1536         inline bool operator()( const PropertyValue& _rProp )
1537         {
1538             return _rProp.Name == m_sName;
1539         }
1540     };
1541 
1542 	//---------------------------------------------------------------------
1543     void OTextLikeImport::adjustDefaultControlProperty()
1544     {
1545         // In OpenOffice.org 2.0, we changed the implementation of the css.form.component.TextField (the model of a text field control),
1546         // so that it now uses another default control. So if we encounter a text field where the *old* default
1547         // control property is writting, we are not allowed to use it
1548         PropertyValueArray::iterator aDefaultControlPropertyPos = ::std::find_if(
1549             m_aValues.begin(),
1550             m_aValues.end(),
1551             EqualName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultControl" ) ) )
1552         );
1553         if ( aDefaultControlPropertyPos != m_aValues.end() )
1554         {
1555             ::rtl::OUString sDefaultControl;
1556             OSL_VERIFY( aDefaultControlPropertyPos->Value >>= sDefaultControl );
1557             if ( sDefaultControl.equalsAscii( "stardiv.one.form.control.Edit" ) )
1558             {
1559                 // complete remove this property value from the array. Today's "default value" of the "DefaultControl"
1560                 // property is sufficient
1561                 ::std::copy(
1562                     aDefaultControlPropertyPos + 1,
1563                     m_aValues.end(),
1564                     aDefaultControlPropertyPos
1565                 );
1566                 m_aValues.resize( m_aValues.size() - 1 );
1567             }
1568         }
1569     }
1570 
1571 	//---------------------------------------------------------------------
1572 	void OTextLikeImport::EndElement()
1573     {
1574         removeRedundantCurrentValue();
1575         adjustDefaultControlProperty();
1576 
1577         // let the base class do the stuff
1578         OControlImport::EndElement();
1579 
1580         // some cleanups
1581         UniReference < XMLTextImportHelper > xTextImportHelper( m_rContext.getGlobalContext().GetTextImport() );
1582         if ( m_xCursor.is() )
1583 	    {
1584 		    // delete the newline which has been imported errornously
1585             // TODO (fs): stole this code somewhere - why don't we fix the text import??
1586 		    m_xCursor->gotoEnd( sal_False );
1587 		    m_xCursor->goLeft( 1, sal_True );
1588             m_xCursor->setString( ::rtl::OUString() );
1589 
1590 		    // reset cursor
1591 		    xTextImportHelper->ResetCursor();
1592 	    }
1593 
1594         if ( m_xOldCursor.is() )
1595 		    xTextImportHelper->SetCursor( m_xOldCursor );
1596 
1597     }
1598 
1599 	//=====================================================================
1600 	//= OListAndComboImport
1601 	//=====================================================================
1602 	//---------------------------------------------------------------------
1603 	OListAndComboImport::OListAndComboImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1604 			const Reference< XNameContainer >& _rxParentContainer,
1605 			OControlElement::ElementType _eType)
1606 		:OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType)
1607 		,m_nEmptyListItems( 0 )
1608 		,m_nEmptyValueItems( 0 )
1609 		,m_bEncounteredLSAttrib( sal_False )
1610         ,m_bLinkWithIndexes( sal_False )
1611 	{
1612 		if (OControlElement::COMBOBOX == m_eElementType)
1613 			enableTrackAttributes();
1614 	}
1615 
1616 	//---------------------------------------------------------------------
1617 	SvXMLImportContext* OListAndComboImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
1618 			const Reference< sax::XAttributeList >& _rxAttrList)
1619 	{
1620 		// is it the "option" sub tag of a listbox ?
1621 		static const ::rtl::OUString s_sOptionElementName = ::rtl::OUString::createFromAscii("option");
1622 		if (s_sOptionElementName == _rLocalName)
1623 			return new OListOptionImport(GetImport(), _nPrefix, _rLocalName, this);
1624 
1625 		// is it the "item" sub tag of a combobox ?
1626 		static const ::rtl::OUString s_sItemElementName = ::rtl::OUString::createFromAscii("item");
1627 		if (s_sItemElementName == _rLocalName)
1628 			return new OComboItemImport(GetImport(), _nPrefix, _rLocalName, this);
1629 
1630 		// everything else
1631 		return OControlImport::CreateChildContext(_nPrefix, _rLocalName, _rxAttrList);
1632 	}
1633 
1634 	//---------------------------------------------------------------------
1635 	void OListAndComboImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1636 	{
1637         m_bLinkWithIndexes = sal_False;
1638 
1639 		OControlImport::StartElement(_rxAttrList);
1640 
1641 		if (OControlElement::COMBOBOX == m_eElementType)
1642 		{
1643 			// for the auto-completion
1644 			// the attribute default does not equal the property default, so in case we did not read this attribute,
1645 			// we have to simulate it
1646 			simulateDefaultedAttribute( OAttributeMetaData::getSpecialAttributeName( SCA_AUTOMATIC_COMPLETION ), PROPERTY_AUTOCOMPLETE, "false");
1647 
1648 			// same for the convert-empty-to-null attribute, which's default is different from the property default
1649 			simulateDefaultedAttribute( OAttributeMetaData::getDatabaseAttributeName( DA_CONVERT_EMPTY ), PROPERTY_EMPTY_IS_NULL, "false");
1650 		}
1651 	}
1652 
1653 	//---------------------------------------------------------------------
1654 	void OListAndComboImport::EndElement()
1655 	{
1656 		// append the list source property the the properties sequence of our importer
1657 		// the string item list
1658 		PropertyValue aItemList;
1659 		aItemList.Name = PROPERTY_STRING_ITEM_LIST;
1660 		aItemList.Value <<= m_aListSource;
1661 		implPushBackPropertyValue(aItemList);
1662 
1663 		if (OControlElement::LISTBOX == m_eElementType)
1664 		{
1665 			OSL_ENSURE((m_aListSource.getLength() + m_nEmptyListItems) == (m_aValueList.getLength() + m_nEmptyValueItems),
1666 				"OListAndComboImport::EndElement: inconsistence between labels and values!");
1667 
1668 			if ( !m_bEncounteredLSAttrib )
1669 			{
1670 				// the value sequence
1671 				PropertyValue aValueList;
1672 				aValueList.Name = PROPERTY_LISTSOURCE;
1673 				aValueList.Value <<= m_aValueList;
1674 				implPushBackPropertyValue(aValueList);
1675 			}
1676 
1677 			// the select sequence
1678 			PropertyValue aSelected;
1679 			aSelected.Name = PROPERTY_SELECT_SEQ;
1680 			aSelected.Value <<= m_aSelectedSeq;
1681 			implPushBackPropertyValue(aSelected);
1682 
1683 			// the default select sequence
1684 			PropertyValue aDefaultSelected;
1685 			aDefaultSelected.Name = PROPERTY_DEFAULT_SELECT_SEQ;
1686 			aDefaultSelected.Value <<= m_aDefaultSelectedSeq;
1687 			implPushBackPropertyValue(aDefaultSelected);
1688 		}
1689 
1690 		OControlImport::EndElement();
1691 
1692         // the external list source, if applicable
1693         if ( m_xElement.is() && m_sCellListSource.getLength() )
1694             m_rContext.registerCellRangeListSource( m_xElement, m_sCellListSource );
1695 	}
1696 
1697 	//---------------------------------------------------------------------
1698 	void OListAndComboImport::doRegisterCellValueBinding( const ::rtl::OUString& _rBoundCellAddress )
1699     {
1700         ::rtl::OUString sBoundCellAddress( _rBoundCellAddress );
1701         if ( m_bLinkWithIndexes )
1702         {
1703             // This is a HACK. We register a string which is no valid address, but allows
1704             // (somewhere else) to determine that a non-standard binding should be created.
1705             // This hack is acceptable for OOo 1.1.1, since the file format for value
1706             // bindings of form controls is to be changed afterwards, anyway.
1707             sBoundCellAddress += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":index" ) );
1708         }
1709 
1710         OControlImport::doRegisterCellValueBinding( sBoundCellAddress );
1711     }
1712 
1713 	//---------------------------------------------------------------------
1714 	bool OListAndComboImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
1715 	{
1716         static const sal_Char* pListSourceAttributeName = OAttributeMetaData::getDatabaseAttributeName(DA_LIST_SOURCE);
1717 		if ( _rLocalName.equalsAscii(pListSourceAttributeName) )
1718 		{
1719 			PropertyValue aListSource;
1720 			aListSource.Name = PROPERTY_LISTSOURCE;
1721 
1722 			// it's the ListSource attribute
1723 			m_bEncounteredLSAttrib = sal_True;
1724 			if ( OControlElement::COMBOBOX == m_eElementType )
1725 			{
1726 				aListSource.Value <<= _rValue;
1727 			}
1728 			else
1729 			{
1730 				// a listbox which has a list-source attribute must have a list-source-type of something
1731 				// not equal to ValueList.
1732 				// In this case, the list-source value is simply the one and only element of the ListSource property.
1733 				Sequence< ::rtl::OUString > aListSourcePropValue( 1 );
1734 				aListSourcePropValue[0] = _rValue;
1735 				aListSource.Value <<= aListSourcePropValue;
1736 			}
1737 
1738 			implPushBackPropertyValue( aListSource );
1739             return true;
1740 		}
1741 
1742         if ( _rLocalName.equalsAscii( OAttributeMetaData::getBindingAttributeName( BA_LIST_CELL_RANGE ) ) )
1743         {
1744             m_sCellListSource = _rValue;
1745             return true;
1746         }
1747 
1748 		if ( _rLocalName.equalsAscii( OAttributeMetaData::getBindingAttributeName( BA_LIST_LINKING_TYPE ) ) )
1749         {
1750             sal_Int16 nLinkageType = 0;
1751             PropertyConversion::convertString(
1752                 m_rContext.getGlobalContext(),
1753                 ::getCppuType( static_cast< sal_Int16* >( NULL ) ),
1754                 _rValue,
1755                 OEnumMapper::getEnumMap( OEnumMapper::epListLinkageType )
1756             ) >>= nLinkageType;
1757 
1758             m_bLinkWithIndexes = ( nLinkageType != 0 );
1759             return true;
1760         }
1761 
1762 		return OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue);
1763 	}
1764 
1765 	//---------------------------------------------------------------------
1766 	void OListAndComboImport::implPushBackLabel(const ::rtl::OUString& _rLabel)
1767 	{
1768 		OSL_ENSURE(!m_nEmptyListItems, "OListAndComboImport::implPushBackValue: label list is already done!");
1769 		if (!m_nEmptyListItems)
1770 			pushBackSequenceElement(m_aListSource, _rLabel);
1771 	}
1772 
1773 	//---------------------------------------------------------------------
1774 	void OListAndComboImport::implPushBackValue(const ::rtl::OUString& _rValue)
1775 	{
1776 		OSL_ENSURE(!m_nEmptyValueItems, "OListAndComboImport::implPushBackValue: value list is already done!");
1777 		if (!m_nEmptyValueItems)
1778 		{
1779 			OSL_ENSURE( !m_bEncounteredLSAttrib, "OListAndComboImport::implPushBackValue: invalid structure! Did you save this document with a version prior SRC641 m?" );
1780 				// We already had the list-source attribute, which means that the ListSourceType is
1781 				// not ValueList, which means that the ListSource should contain only one string in
1782 				// the first element of the sequence
1783 				// All other values in the file are invalid
1784 
1785 			pushBackSequenceElement( m_aValueList, _rValue );
1786 		}
1787 	}
1788 
1789 	//---------------------------------------------------------------------
1790 	void OListAndComboImport::implEmptyLabelFound()
1791 	{
1792 		++m_nEmptyListItems;
1793 	}
1794 
1795 	//---------------------------------------------------------------------
1796 	void OListAndComboImport::implEmptyValueFound()
1797 	{
1798 		++m_nEmptyValueItems;
1799 	}
1800 
1801 	//---------------------------------------------------------------------
1802 	void OListAndComboImport::implSelectCurrentItem()
1803 	{
1804 		OSL_ENSURE((m_aListSource.getLength() + m_nEmptyListItems) == (m_aValueList.getLength() + m_nEmptyValueItems),
1805 			"OListAndComboImport::implSelectCurrentItem: inconsistence between labels and values!");
1806 
1807 		sal_Int16 nItemNumber = (sal_Int16)(m_aListSource.getLength() - 1 + m_nEmptyListItems);
1808 		pushBackSequenceElement(m_aSelectedSeq, nItemNumber);
1809 	}
1810 
1811 	//---------------------------------------------------------------------
1812 	void OListAndComboImport::implDefaultSelectCurrentItem()
1813 	{
1814 		OSL_ENSURE((m_aListSource.getLength() + m_nEmptyListItems) == (m_aValueList.getLength() + m_nEmptyValueItems),
1815 			"OListAndComboImport::implDefaultSelectCurrentItem: inconsistence between labels and values!");
1816 
1817 		sal_Int16 nItemNumber = (sal_Int16)(m_aListSource.getLength() - 1 + m_nEmptyListItems);
1818 		pushBackSequenceElement(m_aDefaultSelectedSeq, nItemNumber);
1819 	}
1820 
1821 	//=====================================================================
1822 	//= OListOptionImport
1823 	//=====================================================================
1824 	//---------------------------------------------------------------------
1825 	OListOptionImport::OListOptionImport(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1826 			const OListAndComboImportRef& _rListBox)
1827 		:SvXMLImportContext(_rImport, _nPrefix, _rName)
1828 		,m_xListBoxImport(_rListBox)
1829 	{
1830 	}
1831 
1832 	//---------------------------------------------------------------------
1833 	void OListOptionImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1834 	{
1835 		// the label and the value
1836         const SvXMLNamespaceMap& rMap = GetImport().GetNamespaceMap();
1837 		const ::rtl::OUString sLabelAttribute = rMap.GetQNameByKey(
1838 			GetPrefix(), ::rtl::OUString::createFromAscii("label"));
1839 		const ::rtl::OUString sValueAttribute = rMap.GetQNameByKey(
1840 			GetPrefix(), ::rtl::OUString::createFromAscii("value"));
1841 
1842 		// -------------------
1843 		// the label attribute
1844 		::rtl::OUString sValue = _rxAttrList->getValueByName(sLabelAttribute);
1845 		sal_Bool bNonexistentAttribute = sal_False;
1846 		if (!sValue.getLength())
1847 			if (0 == _rxAttrList->getTypeByName(sLabelAttribute).getLength())
1848 				// this attribute does not really exist
1849 				bNonexistentAttribute = sal_True;
1850 
1851 		if (bNonexistentAttribute)
1852 			m_xListBoxImport->implEmptyLabelFound();
1853 		else
1854 			m_xListBoxImport->implPushBackLabel( sValue );
1855 
1856 		// -------------------
1857 		// the value attribute
1858 		sValue = _rxAttrList->getValueByName(sValueAttribute);
1859 		bNonexistentAttribute = sal_False;
1860 		if (!sValue.getLength())
1861 			if (0 == _rxAttrList->getTypeByName(sValueAttribute).getLength())
1862 				// this attribute does not really exist
1863 				bNonexistentAttribute = sal_True;
1864 
1865 		if (bNonexistentAttribute)
1866 			m_xListBoxImport->implEmptyValueFound();
1867 		else
1868 			m_xListBoxImport->implPushBackValue( sValue );
1869 
1870 		// the current-selected and selected
1871 		const ::rtl::OUString sSelectedAttribute = rMap.GetQNameByKey(
1872 			GetPrefix(), ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_CURRENT_SELECTED)));
1873 		const ::rtl::OUString sDefaultSelectedAttribute = rMap.GetQNameByKey(
1874 			GetPrefix(), ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_SELECTED)));
1875 
1876 		// propagate the selected flag
1877 		sal_Bool bSelected;
1878 		GetImport().GetMM100UnitConverter().convertBool(bSelected, _rxAttrList->getValueByName(sSelectedAttribute));
1879 		if (bSelected)
1880 			m_xListBoxImport->implSelectCurrentItem();
1881 
1882 		// same for the default selected
1883 		sal_Bool bDefaultSelected;
1884 		GetImport().GetMM100UnitConverter().convertBool(bDefaultSelected, _rxAttrList->getValueByName(sDefaultSelectedAttribute));
1885 		if (bDefaultSelected)
1886 			m_xListBoxImport->implDefaultSelectCurrentItem();
1887 
1888 		SvXMLImportContext::StartElement(_rxAttrList);
1889 	}
1890 
1891 	//=====================================================================
1892 	//= OComboItemImport
1893 	//=====================================================================
1894 	//---------------------------------------------------------------------
1895 	OComboItemImport::OComboItemImport(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1896 			const OListAndComboImportRef& _rListBox)
1897 		:SvXMLImportContext(_rImport, _nPrefix, _rName)
1898 		,m_xListBoxImport(_rListBox)
1899 	{
1900 	}
1901 
1902 	//---------------------------------------------------------------------
1903 	void OComboItemImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1904 	{
1905 		const ::rtl::OUString sLabelAttributeName = GetImport().GetNamespaceMap().GetQNameByKey(
1906 			GetPrefix(), ::rtl::OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCA_LABEL)));
1907 		m_xListBoxImport->implPushBackLabel(_rxAttrList->getValueByName(sLabelAttributeName));
1908 
1909 		SvXMLImportContext::StartElement(_rxAttrList);
1910 	}
1911 
1912 
1913 	//=====================================================================
1914 	//= OColumnWrapperImport
1915 	//=====================================================================
1916 	//---------------------------------------------------------------------
1917 	OColumnWrapperImport::OColumnWrapperImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1918 			const Reference< XNameContainer >& _rxParentContainer)
1919 		:SvXMLImportContext(_rImport.getGlobalContext(), _nPrefix, _rName)
1920 		,m_xParentContainer(_rxParentContainer)
1921         ,m_rFormImport(_rImport)
1922 		,m_rEventManager(_rEventManager)
1923 	{
1924 	}
1925 	//---------------------------------------------------------------------
1926 	SvXMLImportContext* OColumnWrapperImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
1927 		const Reference< sax::XAttributeList >&)
1928 	{
1929 		OControlImport* pReturn = implCreateChildContext(_nPrefix, _rLocalName, OElementNameMap::getElementType(_rLocalName));
1930 		if (pReturn)
1931 		{
1932 			OSL_ENSURE(m_xOwnAttributes.is(), "OColumnWrapperImport::CreateChildContext: had no form:column element!");
1933 			pReturn->addOuterAttributes(m_xOwnAttributes);
1934 		}
1935 		return pReturn;
1936 	}
1937 	//---------------------------------------------------------------------
1938 	void OColumnWrapperImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
1939 	{
1940 		OSL_ENSURE(!m_xOwnAttributes.is(), "OColumnWrapperImport::StartElement: aready have the cloned list!");
1941 
1942 		// clone the attributes
1943 		Reference< XCloneable > xCloneList(_rxAttrList, UNO_QUERY);
1944 		OSL_ENSURE(xCloneList.is(), "OColumnWrapperImport::StartElement: AttributeList not cloneable!");
1945         if ( xCloneList.is() )
1946 		    m_xOwnAttributes = Reference< sax::XAttributeList >(xCloneList->createClone(), UNO_QUERY);
1947 		OSL_ENSURE(m_xOwnAttributes.is(), "OColumnWrapperImport::StartElement: no cloned list!");
1948 	}
1949 
1950 	//---------------------------------------------------------------------
1951 	OControlImport* OColumnWrapperImport::implCreateChildContext(
1952 			sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
1953 			OControlElement::ElementType _eType)
1954 	{
1955 		OSL_ENSURE(	(OControlElement::TEXT == _eType)
1956 				||	(OControlElement::TEXT_AREA == _eType)
1957 				||	(OControlElement::FORMATTED_TEXT == _eType)
1958 				||	(OControlElement::CHECKBOX == _eType)
1959 				||	(OControlElement::LISTBOX == _eType)
1960 				||	(OControlElement::COMBOBOX == _eType)
1961 				||	(OControlElement::TIME == _eType)
1962 				||	(OControlElement::DATE == _eType),
1963 				"OColumnWrapperImport::implCreateChildContext: invalid or unrecognized sub element!");
1964 
1965 		switch (_eType)
1966 		{
1967 			case OControlElement::COMBOBOX:
1968 			case OControlElement::LISTBOX:
1969 				return new OColumnImport<OListAndComboImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType );
1970 
1971 			case OControlElement::PASSWORD:
1972 				return new OColumnImport<OPasswordImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType );
1973 
1974 			case OControlElement::TEXT:
1975 			case OControlElement::TEXT_AREA:
1976 			case OControlElement::FORMATTED_TEXT:
1977 				return new OColumnImport< OTextLikeImport >( m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType );
1978 
1979 			default:
1980 				return new OColumnImport<OControlImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType );
1981 		}
1982 	}
1983 
1984 	//=====================================================================
1985 	//= OGridImport
1986 	//=====================================================================
1987 	//---------------------------------------------------------------------
1988 	OGridImport::OGridImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
1989 			const Reference< XNameContainer >& _rxParentContainer,
1990 			OControlElement::ElementType _eType)
1991 		:OGridImport_Base(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, "column")
1992 	{
1993 		setElementType(_eType);
1994 	}
1995 
1996 	//---------------------------------------------------------------------
1997 	SvXMLImportContext*	OGridImport::implCreateControlWrapper(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName)
1998 	{
1999 		return new OColumnWrapperImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer);
2000 	}
2001 
2002 	//=====================================================================
2003 	//= OFormImport
2004 	//=====================================================================
2005 	//---------------------------------------------------------------------
2006 	OFormImport::OFormImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
2007 			const Reference< XNameContainer >& _rxParentContainer)
2008 		:OFormImport_Base(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, "control")
2009 	{
2010 		enableTrackAttributes();
2011 	}
2012 
2013 	//---------------------------------------------------------------------
2014 	SvXMLImportContext* OFormImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
2015 		const Reference< sax::XAttributeList >& _rxAttrList)
2016 	{
2017 		if( token::IsXMLToken(_rLocalName, token::XML_FORM) )
2018 			return new OFormImport( m_rFormImport, *this, _nPrefix, _rLocalName,
2019 									m_xMeAsContainer);
2020 		else if ( token::IsXMLToken(_rLocalName, token::XML_CONNECTION_RESOURCE) )
2021 			return new OXMLDataSourceImport(GetImport(), _nPrefix, _rLocalName, _rxAttrList,m_xElement);
2022 		else if( (token::IsXMLToken(_rLocalName, token::XML_EVENT_LISTENERS) &&
2023 				 (XML_NAMESPACE_OFFICE == _nPrefix)) ||
2024 			     token::IsXMLToken( _rLocalName, token::XML_PROPERTIES) )
2025 			return OElementImport::CreateChildContext( _nPrefix, _rLocalName,
2026 													   _rxAttrList );
2027 		else
2028 			return implCreateChildContext( _nPrefix, _rLocalName,
2029 						OElementNameMap::getElementType(_rLocalName) );
2030 	}
2031 
2032 	//---------------------------------------------------------------------
2033 	void OFormImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
2034 	{
2035 		m_rFormImport.enterEventContext();
2036 		OFormImport_Base::StartElement(_rxAttrList);
2037 
2038 		// handle the target-frame attribute
2039 		simulateDefaultedAttribute(OAttributeMetaData::getCommonControlAttributeName(CCA_TARGET_FRAME), PROPERTY_TARGETFRAME, "_blank");
2040 	}
2041 
2042 	//---------------------------------------------------------------------
2043 	void OFormImport::EndElement()
2044 	{
2045 		OFormImport_Base::EndElement();
2046 		m_rFormImport.leaveEventContext();
2047 	}
2048 
2049 	//---------------------------------------------------------------------
2050 	SvXMLImportContext*	OFormImport::implCreateControlWrapper(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName)
2051 	{
2052 		OSL_ENSURE( !this, "illegal call to OFormImport::implCreateControlWrapper" );
2053 		return new SvXMLImportContext(GetImport(), _nPrefix, _rLocalName );
2054 	}
2055 
2056 	//---------------------------------------------------------------------
2057 	bool OFormImport::handleAttribute(sal_uInt16 _nNamespaceKey, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
2058 	{
2059 		// handle the master/details field attributes (they're way too special to let the OPropertyImport handle them)
2060 		static const ::rtl::OUString s_sMasterFieldsAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getFormAttributeName(faMasterFields));
2061 		static const ::rtl::OUString s_sDetailFieldsAttributeName = ::rtl::OUString::createFromAscii(OAttributeMetaData::getFormAttributeName(faDetailFiels));
2062 
2063 		if ( s_sMasterFieldsAttributeName == _rLocalName )
2064         {
2065 			implTranslateStringListProperty(PROPERTY_MASTERFIELDS, _rValue);
2066             return true;
2067         }
2068 
2069         if ( s_sDetailFieldsAttributeName == _rLocalName )
2070         {
2071 			implTranslateStringListProperty(PROPERTY_DETAILFIELDS, _rValue);
2072             return true;
2073         }
2074 
2075 		return OFormImport_Base::handleAttribute(_nNamespaceKey, _rLocalName, _rValue);
2076 	}
2077 
2078 	//---------------------------------------------------------------------
2079 	void OFormImport::implTranslateStringListProperty(const ::rtl::OUString& _rPropertyName, const ::rtl::OUString& _rValue)
2080 	{
2081 		PropertyValue aProp;
2082 		aProp.Name = _rPropertyName;
2083 
2084 		Sequence< ::rtl::OUString > aList;
2085 
2086 		// split up the value string
2087 		if (_rValue.getLength())
2088 		{
2089 			// For the moment, we build a vector instead of a Sequence. It's easier to handle because of it's
2090 			// push_back method
2091 			::std::vector< ::rtl::OUString > aElements;
2092 			// estimate the number of tokens
2093 			sal_Int32 nEstimate = 0, nLength = _rValue.getLength();
2094 			const sal_Unicode* pChars = _rValue.getStr();
2095 			for (sal_Int32 i=0; i<nLength; ++i, ++pChars)
2096 				if (*pChars == ',')
2097 					++nEstimate;
2098 			aElements.reserve(nEstimate + 1);
2099 				// that's the worst case. If the string contains the separator character _quoted_, we reserved to much ...
2100 
2101 
2102 			sal_Int32 nElementStart = 0;
2103 			sal_Int32 nNextSep = 0;
2104 			sal_Int32 nElementLength;
2105 			::rtl::OUString sElement;
2106 			do
2107 			{
2108 				// extract the current element
2109 				nNextSep = SvXMLUnitConverter::indexOfComma(
2110                     _rValue, nElementStart);
2111 				if (-1 == nNextSep)
2112 					nNextSep = nLength;
2113 				sElement = _rValue.copy(nElementStart, nNextSep - nElementStart);
2114 
2115 				nElementLength = sElement.getLength();
2116 				// when writing the sequence, we quoted the single elements with " characters
2117 				OSL_ENSURE(	(nElementLength >= 2)
2118 						&&	(sElement.getStr()[0] == '"')
2119 						&&	(sElement.getStr()[nElementLength - 1] == '"'),
2120 						"OFormImport::implTranslateStringListProperty: invalid quoted element name.");
2121 				sElement = sElement.copy(1, nElementLength - 2);
2122 
2123 				aElements.push_back(sElement);
2124 
2125 				// swith to the next element
2126 				nElementStart = 1 + nNextSep;
2127 			}
2128 			while (nElementStart < nLength);
2129 
2130 			::rtl::OUString *pElements = aElements.empty() ? 0 : &aElements[0];
2131 			aList = Sequence< ::rtl::OUString >(pElements, aElements.size());
2132 		}
2133 		else
2134 		{
2135 			OSL_ENSURE(sal_False, "OFormImport::implTranslateStringListProperty: invalid value (empty)!");
2136 		}
2137 
2138 		aProp.Value <<= aList;
2139 
2140 		// add the property to the base class' array
2141 		implPushBackPropertyValue(aProp);
2142 	}
2143 	//=====================================================================
2144 	//= OXMLDataSourceImport
2145 	//=====================================================================
2146 	OXMLDataSourceImport::OXMLDataSourceImport(
2147 					SvXMLImport& _rImport
2148 					,sal_uInt16 nPrfx
2149 					, const ::rtl::OUString& _sLocalName
2150 					,const Reference< ::com::sun::star::xml::sax::XAttributeList > & _xAttrList
2151 					,const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xElement) :
2152 		SvXMLImportContext( _rImport, nPrfx, _sLocalName )
2153 	{
2154 		OSL_ENSURE(_xAttrList.is(),"Attribute list is NULL!");
2155         const SvXMLNamespaceMap& rMap = _rImport.GetNamespaceMap();
2156 
2157 		sal_Int16 nLength = (_xElement.is() && _xAttrList.is()) ? _xAttrList->getLength() : 0;
2158 		for(sal_Int16 i = 0; i < nLength; ++i)
2159 		{
2160 			::rtl::OUString sLocalName;
2161 			::rtl::OUString sAttrName = _xAttrList->getNameByIndex( i );
2162             sal_uInt16 nPrefix = rMap.GetKeyByAttrName( sAttrName, &sLocalName );
2163 
2164 			if  (   ( nPrefix == OAttributeMetaData::getCommonControlAttributeNamespace( CCA_TARGET_LOCATION ) )
2165                 &&  ( sLocalName.equalsAscii( OAttributeMetaData::getCommonControlAttributeName( CCA_TARGET_LOCATION ) ) )
2166                 )
2167 			{
2168                 ::rtl::OUString sValue = _xAttrList->getValueByIndex( i );
2169 
2170 				INetURLObject aURL(sValue);
2171 				if ( aURL.GetProtocol() == INET_PROT_FILE )
2172 					_xElement->setPropertyValue(PROPERTY_DATASOURCENAME,makeAny(sValue));
2173 				else
2174 					_xElement->setPropertyValue(PROPERTY_URL,makeAny(sValue)); // the url is the "sdbc:" string
2175 				break;
2176 			}
2177 		}
2178 	}
2179 	//---------------------------------------------------------------------
2180 	OControlImport* OFormImport::implCreateChildContext(
2181 			sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
2182 			OControlElement::ElementType _eType )
2183 	{
2184 		switch (_eType)
2185 		{
2186 			case OControlElement::TEXT:
2187 			case OControlElement::TEXT_AREA:
2188 			case OControlElement::FORMATTED_TEXT:
2189 				return new OTextLikeImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2190 
2191 			case OControlElement::BUTTON:
2192 			case OControlElement::IMAGE:
2193 			case OControlElement::IMAGE_FRAME:
2194 				return new OButtonImport( m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType );
2195 
2196 			case OControlElement::COMBOBOX:
2197 			case OControlElement::LISTBOX:
2198 				return new OListAndComboImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2199 
2200 			case OControlElement::RADIO:
2201 				return new ORadioImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2202 
2203             case OControlElement::CHECKBOX:
2204 				return new OImagePositionImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2205 
2206 			case OControlElement::PASSWORD:
2207 				return new OPasswordImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2208 
2209 			case OControlElement::FRAME:
2210 			case OControlElement::FIXED_TEXT:
2211 				return new OReferredControlImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2212 
2213 			case OControlElement::GRID:
2214 				return new OGridImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2215 
2216             case OControlElement::VALUERANGE:
2217                 return new OValueRangeImport( m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType );
2218 
2219 			default:
2220 				return new OControlImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType);
2221 		}
2222 	}
2223 
2224 //.........................................................................
2225 }	// namespace xmloff
2226 //.........................................................................
2227 
2228