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