Coverage Report

Created: 2026-02-14 09:37

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