Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/xmloff/source/text/txtparai.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 <xmloff/unointerfacetouniqueidentifiermapper.hxx>
21
22
#include <string_view>
23
24
#include <rtl/ustring.hxx>
25
#include <rtl/ustrbuf.hxx>
26
#include <sal/log.hxx>
27
#include <comphelper/diagnose_ex.hxx>
28
#include <com/sun/star/frame/XModel.hpp>
29
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
30
#include <com/sun/star/text/XTextCursor.hpp>
31
#include <com/sun/star/beans/XPropertySet.hpp>
32
#include <com/sun/star/beans/XPropertySetInfo.hpp>
33
#include <com/sun/star/text/ControlCharacter.hpp>
34
#include <com/sun/star/text/XTextRangeCompare.hpp>
35
#include <com/sun/star/drawing/XShapes.hpp>
36
#include <com/sun/star/container/XEnumerationAccess.hpp>
37
#include <com/sun/star/rdf/XMetadatable.hpp>
38
39
#include <sax/tools/converter.hxx>
40
41
#include <xmloff/prstylei.hxx>
42
#include <xmloff/xmlictxt.hxx>
43
#include <xmloff/xmlimp.hxx>
44
#include <xmloff/xmltoken.hxx>
45
#include <xmloff/xmlnamespace.hxx>
46
#include <xmloff/txtimp.hxx>
47
#include "txtparai.hxx"
48
#include <txtfldi.hxx>
49
#include "XMLFootnoteImportContext.hxx"
50
#include "XMLTextMarkImportContext.hxx"
51
#include "XMLTextFrameContext.hxx"
52
#include <xmloff/XMLCharContext.hxx>
53
#include "XMLTextFrameHyperlinkContext.hxx"
54
#include <xmloff/XMLEventsImportContext.hxx>
55
#include "XMLChangeImportContext.hxx"
56
#include <txtlists.hxx>
57
58
#include "txtparaimphint.hxx"
59
#include "xmllinebreakcontext.hxx"
60
#include "xmlcontentcontrolcontext.hxx"
61
62
using namespace ::com::sun::star;
63
using namespace ::com::sun::star::uno;
64
using namespace ::com::sun::star::text;
65
using namespace ::com::sun::star::drawing;
66
using namespace ::com::sun::star::beans;
67
using namespace ::xmloff::token;
68
using ::com::sun::star::container::XEnumerationAccess;
69
using ::com::sun::star::container::XEnumeration;
70
71
void XMLHints_Impl::push_back(std::unique_ptr<XMLIndexMarkHint_Impl> pHint)
72
29
{
73
29
    m_IndexHintsById.emplace(pHint->GetID(), pHint.get());
74
29
    m_Hints.push_back(std::move(pHint));
75
29
}
76
void XMLHints_Impl::push_back(std::unique_ptr<XMLHint_Impl> pHint)
77
87.2k
{
78
87.2k
    m_Hints.push_back(std::move(pHint));
79
87.2k
}
80
81
XMLCharContext::XMLCharContext(
82
        SvXMLImport& rImport,
83
        const Reference< xml::sax::XFastAttributeList > & xAttrList,
84
        sal_Unicode c,
85
        bool bCount ) :
86
242
    SvXMLImportContext( rImport )
87
242
    ,m_nControl(0)
88
242
    ,m_nCount(1)
89
242
    ,m_c(c)
90
242
{
91
242
    if( !bCount )
92
225
        return;
93
94
17
    for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
95
1
    {
96
1
        if( aIter.getToken() == XML_ELEMENT(TEXT, XML_C) )
97
0
        {
98
0
            sal_Int32 nTmp = aIter.toInt32();
99
0
            if( nTmp > 0 )
100
0
            {
101
0
                if( nTmp > SAL_MAX_UINT16 )
102
0
                    m_nCount = SAL_MAX_UINT16;
103
0
                else
104
0
                    m_nCount = static_cast<sal_uInt16>(nTmp);
105
0
            }
106
0
        }
107
1
        else
108
1
            XMLOFF_WARN_UNKNOWN("xmloff", aIter);
109
1
    }
110
17
}
111
112
XMLCharContext::XMLCharContext(
113
        SvXMLImport& rImp,
114
        sal_Int16 nControl ) :
115
140
    SvXMLImportContext( rImp )
116
140
    ,m_nControl(nControl)
117
140
    ,m_nCount(0)
118
140
    ,m_c(0)
119
140
{
120
140
}
121
122
XMLCharContext::~XMLCharContext()
123
382
{
124
382
}
125
void XMLCharContext::endFastElement(sal_Int32 )
126
373
{
127
373
    if ( !m_nCount )
128
140
        InsertControlCharacter( m_nControl );
129
233
    else
130
233
    {
131
233
        if( 1U == m_nCount )
132
233
        {
133
233
            OUString sBuff( &m_c, 1 );
134
233
            InsertString(sBuff);
135
233
        }
136
0
        else
137
0
        {
138
0
            OUStringBuffer sBuff(static_cast<int>(m_nCount));
139
0
            while( m_nCount-- )
140
0
                sBuff.append( &m_c, 1 );
141
142
0
            InsertString(sBuff.makeStringAndClear() );
143
0
        }
144
233
    }
145
373
}
146
void XMLCharContext::InsertControlCharacter(sal_Int16   _nControl)
147
140
{
148
140
    GetImport().GetTextImport()->InsertControlCharacter( _nControl );
149
140
}
150
void XMLCharContext::InsertString(const OUString& _sString)
151
233
{
152
233
    GetImport().GetTextImport()->InsertString( _sString );
153
233
}
154
155
namespace {
156
157
/** import start of reference (<text:reference-start>) */
158
class XMLStartReferenceContext_Impl : public SvXMLImportContext
159
{
160
public:
161
162
    // Do everything in constructor. Well ...
163
    XMLStartReferenceContext_Impl (
164
        SvXMLImport& rImport,
165
        XMLHints_Impl& rHints,
166
        const Reference<xml::sax::XFastAttributeList> & xAttrList);
167
168
    static bool FindName(
169
        const Reference<xml::sax::XFastAttributeList> & xAttrList,
170
        OUString& rName);
171
};
172
173
}
174
175
XMLStartReferenceContext_Impl::XMLStartReferenceContext_Impl(
176
    SvXMLImport& rImport,
177
    XMLHints_Impl& rHints,
178
    const Reference<xml::sax::XFastAttributeList> & xAttrList) :
179
15
        SvXMLImportContext(rImport)
180
15
{
181
15
    OUString sName;
182
183
15
    if (FindName(xAttrList, sName))
184
4
    {
185
4
        std::unique_ptr<XMLHint_Impl> pHint(new XMLReferenceHint_Impl(
186
4
            sName, rImport.GetTextImport()->GetCursor()->getStart()));
187
188
        // degenerates to point reference, if no end is found!
189
4
        pHint->SetEnd(rImport.GetTextImport()->GetCursor()->getStart() );
190
191
4
        rHints.push_back(std::move(pHint));
192
4
    }
193
15
}
194
195
bool XMLStartReferenceContext_Impl::FindName(
196
    const Reference<xml::sax::XFastAttributeList> & xAttrList,
197
    OUString& rName)
198
18
{
199
18
    bool bNameOK( false );
200
201
    // find name attribute first
202
18
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
203
7
    {
204
7
        if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_NAME) )
205
7
        {
206
7
            rName = aIter.toString();
207
7
            bNameOK = true;
208
7
            break;
209
7
        }
210
7
    }
211
212
18
    return bNameOK;
213
18
}
214
215
namespace {
216
217
/** import end of reference (<text:reference-end>) */
218
class XMLEndReferenceContext_Impl : public SvXMLImportContext
219
{
220
public:
221
222
    // Do everything in constructor. Well ...
223
    XMLEndReferenceContext_Impl(
224
        SvXMLImport& rImport,
225
        const XMLHints_Impl& rHints,
226
        const Reference<xml::sax::XFastAttributeList> & xAttrList);
227
};
228
229
}
230
231
XMLEndReferenceContext_Impl::XMLEndReferenceContext_Impl(
232
    SvXMLImport& rImport,
233
    const XMLHints_Impl& rHints,
234
    const Reference<xml::sax::XFastAttributeList> & xAttrList) :
235
3
        SvXMLImportContext(rImport)
236
3
{
237
3
    OUString sName;
238
239
    // borrow from XMLStartReferenceContext_Impl
240
3
    if (!XMLStartReferenceContext_Impl::FindName(xAttrList, sName))
241
0
        return;
242
243
    // search for reference start
244
3
    for (const auto& rHintPtr : rHints.GetHints())
245
3
    {
246
3
        XMLHint_Impl *const pHint = rHintPtr.get();
247
3
        if ( pHint->IsReference() &&
248
3
             sName == static_cast<XMLReferenceHint_Impl *>(pHint)->GetRefName() )
249
2
        {
250
            // set end and stop searching
251
2
            pHint->SetEnd(GetImport().GetTextImport()->
252
2
                                 GetCursor()->getStart() );
253
2
            break;
254
2
        }
255
3
    }
256
    // else: no start (in this paragraph) -> ignore
257
3
}
258
259
namespace {
260
261
class XMLImpHyperlinkContext_Impl : public SvXMLImportContext
262
{
263
    XMLHints_Impl&  m_rHints;
264
    XMLHyperlinkHint_Impl   *mpHint;
265
266
    bool&       mrbIgnoreLeadingSpace;
267
268
public:
269
270
271
    XMLImpHyperlinkContext_Impl(
272
            SvXMLImport& rImport,
273
            sal_Int32 nElement,
274
            const Reference< xml::sax::XFastAttributeList > & xAttrList,
275
            XMLHints_Impl& rHints,
276
            bool& rIgnLeadSpace );
277
278
    virtual ~XMLImpHyperlinkContext_Impl() override;
279
280
    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
281
        sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
282
283
    virtual void SAL_CALL characters( const OUString& rChars ) override;
284
};
285
286
}
287
288
XMLImpHyperlinkContext_Impl::XMLImpHyperlinkContext_Impl(
289
    SvXMLImport& rImport,
290
    sal_Int32 /*nElement*/,
291
    const Reference< xml::sax::XFastAttributeList > & xAttrList,
292
    XMLHints_Impl& rHints,
293
    bool& rIgnLeadSpace )
294
240
    : SvXMLImportContext( rImport )
295
240
    , m_rHints( rHints )
296
240
    , mpHint( new XMLHyperlinkHint_Impl( GetImport().GetTextImport()->GetCursorAsRange()->getStart() ) )
297
240
    , mrbIgnoreLeadingSpace( rIgnLeadSpace )
298
240
{
299
240
    OUString sShow;
300
301
240
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
302
0
    {
303
0
        OUString sValue = aIter.toString();
304
0
        switch (aIter.getToken())
305
0
        {
306
0
        case XML_ELEMENT(XLINK, XML_HREF):
307
0
            mpHint->SetHRef( GetImport().GetAbsoluteReference( sValue ) );
308
0
            break;
309
0
        case XML_ELEMENT(OFFICE, XML_NAME):
310
0
            mpHint->SetName( sValue );
311
0
            break;
312
0
        case XML_ELEMENT(OFFICE, XML_TARGET_FRAME_NAME):
313
0
            mpHint->SetTargetFrameName( sValue );
314
0
            break;
315
0
        case XML_ELEMENT(XLINK, XML_SHOW):
316
0
            sShow = sValue;
317
0
            break;
318
0
        case XML_ELEMENT(TEXT, XML_STYLE_NAME):
319
0
            mpHint->SetStyleName( sValue );
320
0
            break;
321
0
        case XML_ELEMENT(TEXT, XML_VISITED_STYLE_NAME):
322
0
            mpHint->SetVisitedStyleName( sValue );
323
0
            break;
324
0
        case XML_ELEMENT(XLINK, XML_TYPE):
325
            // don't show warning for this
326
0
            break;
327
0
        default:
328
0
            XMLOFF_WARN_UNKNOWN("xmloff", aIter);
329
0
        }
330
0
    }
331
332
240
    if( !sShow.isEmpty() && mpHint->GetTargetFrameName().isEmpty() )
333
0
    {
334
0
        if( IsXMLToken( sShow, XML_NEW ) )
335
0
            mpHint->SetTargetFrameName(
336
0
                    u"_blank"_ustr );
337
0
        else if( IsXMLToken( sShow, XML_REPLACE ) )
338
0
            mpHint->SetTargetFrameName(
339
0
                    u"_self"_ustr );
340
0
    }
341
342
240
    if ( mpHint->GetHRef().isEmpty() )
343
240
    {
344
        // hyperlink without a URL is not imported.
345
240
        delete mpHint;
346
240
        mpHint = nullptr;
347
240
    }
348
0
    else
349
0
    {
350
0
        m_rHints.push_back(std::unique_ptr<XMLHyperlinkHint_Impl>(mpHint));
351
0
    }
352
240
}
353
354
XMLImpHyperlinkContext_Impl::~XMLImpHyperlinkContext_Impl()
355
240
{
356
240
    if (mpHint)
357
0
        mpHint->SetEnd( GetImport().GetTextImport()
358
0
                            ->GetCursorAsRange()->getStart() );
359
240
}
360
361
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpHyperlinkContext_Impl::createFastChildContext(
362
    sal_Int32 nElement,
363
    const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
364
155
{
365
155
    if ( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
366
0
    {
367
0
        XMLEventsImportContext* pCtxt = new XMLEventsImportContext(GetImport());
368
0
        if (mpHint)
369
0
            mpHint->SetEventsContext(pCtxt);
370
0
        return pCtxt;
371
0
    }
372
155
    else
373
155
    {
374
155
        return XMLImpSpanContext_Impl::CreateSpanContext(
375
155
            GetImport(), nElement, xAttrList,
376
155
            m_rHints, mrbIgnoreLeadingSpace );
377
155
    }
378
155
}
379
380
void XMLImpHyperlinkContext_Impl::characters( const OUString& rChars )
381
130
{
382
130
    GetImport().GetTextImport()->InsertString( rChars, mrbIgnoreLeadingSpace );
383
130
}
384
385
namespace {
386
387
class XMLImpRubyBaseContext_Impl : public SvXMLImportContext
388
{
389
    XMLHints_Impl&  m_rHints;
390
391
    bool&       rIgnoreLeadingSpace;
392
393
public:
394
395
396
    XMLImpRubyBaseContext_Impl(
397
            SvXMLImport& rImport,
398
            sal_Int32 nElement,
399
            const Reference< xml::sax::XFastAttributeList > & xAttrList,
400
            XMLHints_Impl& rHints,
401
            bool& rIgnLeadSpace );
402
403
    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
404
        sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
405
406
    virtual void SAL_CALL characters( const OUString& rChars ) override;
407
};
408
409
}
410
411
XMLImpRubyBaseContext_Impl::XMLImpRubyBaseContext_Impl(
412
        SvXMLImport& rImport,
413
        sal_Int32 /*nElement*/,
414
        const Reference< xml::sax::XFastAttributeList > &,
415
        XMLHints_Impl& rHints,
416
        bool& rIgnLeadSpace )
417
2.52k
    : SvXMLImportContext( rImport )
418
2.52k
    , m_rHints( rHints )
419
2.52k
    , rIgnoreLeadingSpace( rIgnLeadSpace )
420
2.52k
{
421
2.52k
}
422
423
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpRubyBaseContext_Impl::createFastChildContext(
424
    sal_Int32 nElement,
425
    const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
426
2.10k
{
427
2.10k
    return XMLImpSpanContext_Impl::CreateSpanContext( GetImport(), nElement, xAttrList,
428
2.10k
                               m_rHints, rIgnoreLeadingSpace );
429
2.10k
}
430
431
void XMLImpRubyBaseContext_Impl::characters( const OUString& rChars )
432
4.33k
{
433
4.33k
    GetImport().GetTextImport()->InsertString( rChars, rIgnoreLeadingSpace );
434
4.33k
}
435
436
namespace {
437
438
class XMLImpRubyContext_Impl : public SvXMLImportContext
439
{
440
    XMLHints_Impl&  m_rHints;
441
442
    bool&       rIgnoreLeadingSpace;
443
444
    Reference < XTextRange > m_xStart;
445
    OUString        m_sStyleName;
446
    OUString        m_sTextStyleName;
447
    OUString        m_sText;
448
449
public:
450
451
452
    XMLImpRubyContext_Impl(
453
            SvXMLImport& rImport,
454
            sal_Int32 nElement,
455
            const Reference< xml::sax::XFastAttributeList > & xAttrList,
456
            XMLHints_Impl& rHints,
457
            bool& rIgnLeadSpace );
458
459
    virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
460
461
    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
462
        sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
463
464
0
    void SetTextStyleName( const OUString& s ) { m_sTextStyleName = s; }
465
773
    void AppendText( std::u16string_view s ) { m_sText += s; }
466
};
467
468
class XMLImpRubyTextContext_Impl : public SvXMLImportContext
469
{
470
    XMLImpRubyContext_Impl & m_rRubyContext;
471
472
public:
473
474
475
    XMLImpRubyTextContext_Impl(
476
            SvXMLImport& rImport,
477
            sal_Int32 nElement,
478
            const Reference< xml::sax::XFastAttributeList > & xAttrList,
479
            XMLImpRubyContext_Impl & rParent );
480
481
    virtual void SAL_CALL characters( const OUString& rChars ) override;
482
};
483
484
}
485
486
XMLImpRubyTextContext_Impl::XMLImpRubyTextContext_Impl(
487
        SvXMLImport& rImport,
488
        sal_Int32 /*nElement*/,
489
        const Reference< xml::sax::XFastAttributeList > & xAttrList,
490
        XMLImpRubyContext_Impl & rParent )
491
607
    : SvXMLImportContext( rImport )
492
607
    , m_rRubyContext( rParent )
493
607
{
494
607
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
495
0
    {
496
0
        if( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME) )
497
0
        {
498
0
            m_rRubyContext.SetTextStyleName( aIter.toString() );
499
0
            break;
500
0
        }
501
0
    }
502
607
}
503
504
void XMLImpRubyTextContext_Impl::characters( const OUString& rChars )
505
773
{
506
773
    m_rRubyContext.AppendText( rChars );
507
773
}
508
509
510
XMLImpRubyContext_Impl::XMLImpRubyContext_Impl(
511
        SvXMLImport& rImport,
512
        sal_Int32 /*nElement*/,
513
        const Reference< xml::sax::XFastAttributeList > & xAttrList,
514
        XMLHints_Impl& rHints,
515
        bool& rIgnLeadSpace )
516
2.56k
    : SvXMLImportContext( rImport )
517
2.56k
    , m_rHints( rHints )
518
2.56k
    , rIgnoreLeadingSpace( rIgnLeadSpace )
519
2.56k
    , m_xStart( GetImport().GetTextImport()->GetCursorAsRange()->getStart() )
520
2.56k
{
521
2.56k
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
522
2.26k
    {
523
2.26k
        if( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME) )
524
2.25k
        {
525
2.25k
            m_sStyleName = aIter.toString();
526
2.25k
            break;
527
2.25k
        }
528
2.26k
    }
529
2.56k
}
530
531
void XMLImpRubyContext_Impl::endFastElement(sal_Int32 )
532
2.08k
{
533
2.08k
    const rtl::Reference < XMLTextImportHelper > xTextImport(
534
2.08k
        GetImport().GetTextImport());
535
2.08k
    const Reference < XTextCursor > xAttrCursor(
536
2.08k
        xTextImport->GetText()->createTextCursorByRange( m_xStart ));
537
2.08k
    if (!xAttrCursor.is())
538
44
    {
539
44
        SAL_WARN("xmloff.text", "cannot insert ruby");
540
44
        return;
541
44
    }
542
2.04k
    xAttrCursor->gotoRange(xTextImport->GetCursorAsRange()->getStart(),
543
2.04k
            true);
544
2.04k
    xTextImport->SetRuby( GetImport(), xAttrCursor,
545
2.04k
         m_sStyleName, m_sTextStyleName, m_sText );
546
2.04k
}
547
548
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpRubyContext_Impl::createFastChildContext(
549
    sal_Int32 nElement,
550
    const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
551
3.19k
{
552
3.19k
    if( nElement == XML_ELEMENT(TEXT, XML_RUBY_BASE) )
553
2.52k
        return new XMLImpRubyBaseContext_Impl( GetImport(), nElement,
554
2.52k
                                                   xAttrList,
555
2.52k
                                                   m_rHints,
556
2.52k
                                                   rIgnoreLeadingSpace );
557
667
    else if( nElement == XML_ELEMENT(TEXT, XML_RUBY_TEXT) )
558
607
        return new XMLImpRubyTextContext_Impl( GetImport(), nElement,
559
607
                                                       xAttrList,
560
607
                                                       *this );
561
60
    else
562
60
        XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
563
564
60
    return nullptr;
565
3.19k
}
566
567
namespace {
568
569
/** for text:meta and text:meta-field
570
 */
571
class XMLMetaImportContextBase : public SvXMLImportContext
572
{
573
    XMLHints_Impl&    m_rHints;
574
575
    bool& m_rIgnoreLeadingSpace;
576
577
    /// start position
578
    Reference<XTextRange> m_xStart;
579
580
protected:
581
    OUString m_XmlId;
582
583
public:
584
585
    XMLMetaImportContextBase(
586
        SvXMLImport& i_rImport,
587
        const sal_Int32 nElement,
588
        XMLHints_Impl& i_rHints,
589
        bool & i_rIgnoreLeadingSpace );
590
591
    virtual void SAL_CALL startFastElement(
592
            sal_Int32 nElement,
593
            const Reference<xml::sax::XFastAttributeList> & i_xAttrList) override;
594
595
    virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
596
597
    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
598
        sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
599
600
    virtual void SAL_CALL characters( const OUString& i_rChars ) override;
601
602
    virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter);
603
604
    virtual void InsertMeta(const Reference<XTextRange> & i_xInsertionRange)
605
        = 0;
606
};
607
608
}
609
610
XMLMetaImportContextBase::XMLMetaImportContextBase(
611
        SvXMLImport& i_rImport,
612
        const sal_Int32 /*i_nElement*/,
613
        XMLHints_Impl& i_rHints,
614
        bool & i_rIgnoreLeadingSpace )
615
4
    : SvXMLImportContext( i_rImport )
616
4
    , m_rHints( i_rHints )
617
4
    , m_rIgnoreLeadingSpace( i_rIgnoreLeadingSpace )
618
4
    , m_xStart( GetImport().GetTextImport()->GetCursorAsRange()->getStart() )
619
4
{
620
4
}
621
622
void XMLMetaImportContextBase::startFastElement(
623
        sal_Int32 /*nElement*/,
624
        const Reference<xml::sax::XFastAttributeList> & xAttrList)
625
4
{
626
4
    for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
627
0
        ProcessAttribute(aIter);
628
4
}
629
630
void XMLMetaImportContextBase::endFastElement(sal_Int32 )
631
0
{
632
0
    SAL_WARN_IF(!m_xStart.is(), "xmloff.text", "no mxStart?");
633
0
    if (!m_xStart.is()) return;
634
635
0
    const Reference<XTextRange> xEndRange(
636
0
        GetImport().GetTextImport()->GetCursorAsRange()->getStart() );
637
638
    // create range for insertion
639
0
    const Reference<XTextCursor> xInsertionCursor(
640
0
        GetImport().GetTextImport()->GetText()->createTextCursorByRange(
641
0
            xEndRange) );
642
0
    xInsertionCursor->gotoRange(m_xStart, true);
643
644
0
    InsertMeta(xInsertionCursor);
645
0
}
646
647
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLMetaImportContextBase::createFastChildContext(
648
    sal_Int32 nElement,
649
    const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
650
41
{
651
41
    return XMLImpSpanContext_Impl::CreateSpanContext( GetImport(), nElement,
652
41
        xAttrList, m_rHints, m_rIgnoreLeadingSpace );
653
41
}
654
655
void XMLMetaImportContextBase::characters( const OUString& i_rChars )
656
76
{
657
76
    GetImport().GetTextImport()->InsertString(i_rChars, m_rIgnoreLeadingSpace);
658
76
}
659
660
void XMLMetaImportContextBase::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
661
0
{
662
0
    if ( aIter.getToken() == XML_ELEMENT(XML, XML_ID) )
663
0
        m_XmlId = aIter.toString();
664
0
    else
665
0
        XMLOFF_WARN_UNKNOWN("xmloff", aIter);
666
0
}
667
668
namespace {
669
670
/** text:meta */
671
class XMLMetaImportContext : public XMLMetaImportContextBase
672
{
673
    // RDFa
674
    bool m_bHaveAbout;
675
    OUString m_sAbout;
676
    OUString m_sProperty;
677
    OUString m_sContent;
678
    OUString m_sDatatype;
679
680
public:
681
682
    XMLMetaImportContext(
683
        SvXMLImport& i_rImport,
684
        sal_Int32 nElement,
685
        XMLHints_Impl& i_rHints,
686
        bool & i_rIgnoreLeadingSpace );
687
688
    virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
689
690
    virtual void InsertMeta(const Reference<XTextRange> & i_xInsertionRange) override;
691
};
692
693
}
694
695
XMLMetaImportContext::XMLMetaImportContext(
696
        SvXMLImport& i_rImport,
697
        sal_Int32 nElement,
698
        XMLHints_Impl& i_rHints,
699
        bool & i_rIgnoreLeadingSpace )
700
4
    : XMLMetaImportContextBase( i_rImport, nElement,
701
4
            i_rHints, i_rIgnoreLeadingSpace )
702
4
    , m_bHaveAbout(false)
703
4
{
704
4
}
705
706
void XMLMetaImportContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
707
0
{
708
0
    switch (aIter.getToken())
709
0
    {
710
        // RDFa
711
0
        case XML_ELEMENT(XHTML, XML_ABOUT):
712
0
            m_sAbout = aIter.toString();
713
0
            m_bHaveAbout = true;
714
0
            break;
715
0
        case XML_ELEMENT(XHTML, XML_PROPERTY):
716
0
            m_sProperty = aIter.toString();
717
0
            break;
718
0
        case XML_ELEMENT(XHTML, XML_CONTENT):
719
0
            m_sContent = aIter.toString();
720
0
            break;
721
0
        case XML_ELEMENT(XHTML, XML_DATATYPE):
722
0
            m_sDatatype = aIter.toString();
723
0
            break;
724
0
        default:
725
0
            XMLMetaImportContextBase::ProcessAttribute(aIter);
726
0
    }
727
0
}
728
729
void XMLMetaImportContext::InsertMeta(
730
    const Reference<XTextRange> & i_xInsertionRange)
731
0
{
732
0
    SAL_WARN_IF(m_bHaveAbout == m_sProperty.isEmpty(), "xmloff.text", "XMLMetaImportContext::InsertMeta: invalid RDFa?");
733
0
    if (!m_XmlId.isEmpty() || (m_bHaveAbout && !m_sProperty.isEmpty()))
734
0
    {
735
        // insert mark
736
0
        const uno::Reference<rdf::XMetadatable> xMeta(
737
0
            XMLTextMarkImportContext::CreateAndInsertMark(
738
0
                GetImport(),
739
0
                u"com.sun.star.text.InContentMetadata"_ustr,
740
0
                OUString(),
741
0
                i_xInsertionRange, m_XmlId),
742
0
            uno::UNO_QUERY);
743
0
        SAL_WARN_IF(!xMeta.is(), "xmloff.text", "cannot insert Meta?");
744
745
0
        if (xMeta.is() && m_bHaveAbout)
746
0
        {
747
0
            GetImport().AddRDFa(xMeta,
748
0
                m_sAbout, m_sProperty, m_sContent, m_sDatatype);
749
0
        }
750
0
    }
751
0
    else
752
0
    {
753
0
        SAL_INFO("xmloff.text", "invalid <text:meta>: no xml:id, no valid RDFa");
754
0
    }
755
0
}
756
757
namespace {
758
759
/** text:meta-field */
760
class XMLMetaFieldImportContext : public XMLMetaImportContextBase
761
{
762
    OUString m_DataStyleName;
763
764
public:
765
766
    XMLMetaFieldImportContext(
767
        SvXMLImport& i_rImport,
768
        sal_Int32 nElement,
769
        XMLHints_Impl& i_rHints,
770
        bool & i_rIgnoreLeadingSpace );
771
772
    virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
773
774
    virtual void InsertMeta(const Reference<XTextRange> & i_xInsertionRange) override;
775
};
776
777
}
778
779
XMLMetaFieldImportContext::XMLMetaFieldImportContext(
780
        SvXMLImport& i_rImport,
781
        sal_Int32 nElement,
782
        XMLHints_Impl& i_rHints,
783
        bool & i_rIgnoreLeadingSpace )
784
0
    : XMLMetaImportContextBase( i_rImport, nElement,
785
0
            i_rHints, i_rIgnoreLeadingSpace )
786
0
{
787
0
}
788
789
void XMLMetaFieldImportContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
790
0
{
791
0
    switch (aIter.getToken())
792
0
    {
793
0
        case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
794
0
            m_DataStyleName = aIter.toString();
795
0
            break;
796
0
        default:
797
0
            XMLMetaImportContextBase::ProcessAttribute(aIter);
798
0
    }
799
0
}
800
801
void XMLMetaFieldImportContext::InsertMeta(
802
    const Reference<XTextRange> & i_xInsertionRange)
803
0
{
804
0
    if (!m_XmlId.isEmpty()) // valid?
805
0
    {
806
        // insert mark
807
0
        const Reference<XPropertySet> xPropertySet(
808
0
            XMLTextMarkImportContext::CreateAndInsertMark(
809
0
                GetImport(),
810
0
                u"com.sun.star.text.textfield.MetadataField"_ustr,
811
0
                OUString(),
812
0
                i_xInsertionRange, m_XmlId),
813
0
            UNO_QUERY);
814
0
        SAL_WARN_IF(!xPropertySet.is(), "xmloff.text", "cannot insert MetaField?");
815
0
        if (!xPropertySet.is()) return;
816
817
0
        if (!m_DataStyleName.isEmpty())
818
0
        {
819
0
            bool isDefaultLanguage(true);
820
821
0
            const sal_Int32 nKey( GetImport().GetTextImport()->GetDataStyleKey(
822
0
                                   m_DataStyleName, & isDefaultLanguage) );
823
824
0
            if (-1 != nKey)
825
0
            {
826
0
                OUString sPropertyIsFixedLanguage(u"IsFixedLanguage"_ustr);
827
0
                xPropertySet->setPropertyValue(u"NumberFormat"_ustr, Any(nKey));
828
0
                if ( xPropertySet->getPropertySetInfo()->
829
0
                        hasPropertyByName( sPropertyIsFixedLanguage ) )
830
0
                {
831
0
                    xPropertySet->setPropertyValue( sPropertyIsFixedLanguage,
832
0
                        Any(!isDefaultLanguage) );
833
0
                }
834
0
            }
835
0
        }
836
0
    }
837
0
    else
838
0
    {
839
0
        SAL_INFO("xmloff.text", "invalid <text:meta-field>: no xml:id");
840
0
    }
841
0
}
842
843
namespace {
844
845
/**
846
 * Process index marks.
847
 *
848
 * All *-mark-end index marks should instantiate *this* class (because
849
 * it doesn't process attributes other than ID), while the *-mark and
850
 * *-mark-start classes should instantiate the appropriate subclasses.
851
 */
852
class XMLIndexMarkImportContext_Impl : public SvXMLImportContext
853
{
854
    XMLHints_Impl& m_rHints;
855
    OUString sID;
856
857
public:
858
859
    XMLIndexMarkImportContext_Impl(
860
        SvXMLImport& rImport,
861
        XMLHints_Impl& rHints);
862
863
    void SAL_CALL startFastElement(sal_Int32 nElement, const Reference<xml::sax::XFastAttributeList> & xAttrList) override;
864
865
protected:
866
867
    /// process all attributes
868
    void ProcessAttributes(sal_Int32 nElement, const Reference<xml::sax::XFastAttributeList> & xAttrList,
869
                           Reference<beans::XPropertySet>& rPropSet);
870
871
    /**
872
     * All marks can be created immediately. Since we don't care about
873
     * the element content, ProcessAttribute should set the properties
874
     * immediately.
875
     *
876
     * This method tolerates an empty PropertySet; subclasses however
877
     * are not expected to.
878
     */
879
    virtual void ProcessAttribute(sal_Int32 nElement,
880
                                  const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
881
                                  Reference<beans::XPropertySet>& rPropSet);
882
883
    static void GetServiceName(OUString& sServiceName,
884
                               sal_Int32 nElement);
885
886
    bool CreateMark(Reference<beans::XPropertySet>& rPropSet,
887
                        const OUString& rServiceName);
888
};
889
890
}
891
892
XMLIndexMarkImportContext_Impl::XMLIndexMarkImportContext_Impl(
893
    SvXMLImport& rImport,
894
    XMLHints_Impl& rHints)
895
35
    : SvXMLImportContext(rImport)
896
35
    , m_rHints(rHints)
897
35
{
898
35
}
899
900
void XMLIndexMarkImportContext_Impl::startFastElement(
901
    sal_Int32 nElement,
902
    const Reference<xml::sax::XFastAttributeList> & xAttrList)
903
35
{
904
    // get Cursor position (needed for all cases)
905
35
    Reference<XTextRange> xPos(
906
35
        GetImport().GetTextImport()->GetCursor()->getStart());
907
35
    Reference<beans::XPropertySet> xMark;
908
909
35
    switch (nElement)
910
35
    {
911
2
        case XML_ELEMENT(TEXT, XML_TOC_MARK):
912
6
        case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
913
31
        case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
914
31
        {
915
            // single mark: create mark and insert
916
31
            OUString sService;
917
31
            GetServiceName(sService, nElement);
918
31
            if (CreateMark(xMark, sService))
919
29
            {
920
29
                ProcessAttributes(nElement, xAttrList, xMark);
921
29
                m_rHints.push_back(
922
29
                    std::make_unique<XMLIndexMarkHint_Impl>(xMark, xPos));
923
29
            }
924
            // else: can't create mark -> ignore
925
31
            break;
926
6
        }
927
928
0
        case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
929
0
        case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
930
0
        case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
931
0
        {
932
            // start: create mark and insert (if ID is found)
933
0
            OUString sService;
934
0
            GetServiceName(sService, nElement);
935
0
            if (CreateMark(xMark, sService))
936
0
            {
937
0
                ProcessAttributes(nElement, xAttrList, xMark);
938
0
                if (!sID.isEmpty())
939
0
                {
940
                    // process only if we find an ID
941
0
                    m_rHints.push_back(
942
0
                        std::make_unique<XMLIndexMarkHint_Impl>(xMark, xPos, sID));
943
0
                }
944
                // else: no ID -> we'll never find the end -> ignore
945
0
            }
946
            // else: can't create mark -> ignore
947
0
            break;
948
0
        }
949
950
3
        case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
951
4
        case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
952
4
        case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
953
4
        {
954
            // end: search for ID and set end of mark
955
956
            // call process attributes with empty XPropertySet:
957
4
            ProcessAttributes(nElement, xAttrList, xMark);
958
4
            if (!sID.isEmpty())
959
0
            {
960
                // if we have an ID, find the hint and set the end position
961
0
                XMLIndexMarkHint_Impl *const pHint = m_rHints.GetIndexHintById(sID);
962
0
                if (pHint)
963
                    // set end and stop searching
964
0
                    pHint->SetEnd(xPos);
965
0
            }
966
            // else: no ID -> ignore
967
4
            break;
968
4
        }
969
970
0
        default:
971
0
            SAL_WARN("xmloff.text", "unknown index mark type!");
972
0
            break;
973
35
    }
974
35
}
975
976
void XMLIndexMarkImportContext_Impl::ProcessAttributes(
977
    sal_Int32 nElement,
978
    const Reference<xml::sax::XFastAttributeList> & xAttrList,
979
    Reference<beans::XPropertySet>& rPropSet)
980
33
{
981
    // process attributes
982
33
    for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
983
0
    {
984
0
        ProcessAttribute(nElement, aIter, rPropSet);
985
0
    }
986
33
}
987
988
void XMLIndexMarkImportContext_Impl::ProcessAttribute(
989
    sal_Int32 nElement,
990
    const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
991
    Reference<beans::XPropertySet>& rPropSet)
992
0
{
993
    // we only know ID + string-value attribute;
994
    // (former: marks, latter: -start + -end-marks)
995
    // the remainder is handled in sub-classes
996
0
    switch (nElement)
997
0
    {
998
0
        case XML_ELEMENT(TEXT, XML_TOC_MARK):
999
0
        case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
1000
0
        case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
1001
0
            if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_STRING_VALUE) )
1002
0
            {
1003
0
                rPropSet->setPropertyValue(u"AlternativeText"_ustr, uno::Any(aIter.toString()));
1004
0
            }
1005
            // else: ignore!
1006
0
            break;
1007
1008
0
        case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
1009
0
        case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
1010
0
        case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
1011
0
        case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
1012
0
        case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
1013
0
        case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
1014
0
            if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_ID) )
1015
0
            {
1016
0
                sID = aIter.toString();
1017
0
            }
1018
            // else: ignore
1019
0
            break;
1020
1021
0
        default:
1022
0
            XMLOFF_WARN_UNKNOWN("xmloff", aIter);
1023
0
            break;
1024
0
    }
1025
0
}
1026
1027
1028
void XMLIndexMarkImportContext_Impl::GetServiceName(
1029
    OUString& sServiceName,
1030
    sal_Int32 nElement)
1031
31
{
1032
31
    switch (nElement)
1033
31
    {
1034
2
        case XML_ELEMENT(TEXT, XML_TOC_MARK):
1035
2
        case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
1036
2
        case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
1037
2
        {
1038
2
            sServiceName = "com.sun.star.text.ContentIndexMark";
1039
2
            break;
1040
2
        }
1041
1042
4
        case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
1043
4
        case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
1044
4
        case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
1045
4
        {
1046
4
            sServiceName = "com.sun.star.text.UserIndexMark";
1047
4
            break;
1048
4
        }
1049
1050
25
        case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
1051
25
        case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
1052
25
        case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
1053
25
        {
1054
25
            sServiceName = "com.sun.star.text.DocumentIndexMark";
1055
25
            break;
1056
25
        }
1057
1058
0
        default:
1059
0
        {
1060
0
            XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
1061
0
            sServiceName.clear();
1062
0
            break;
1063
0
        }
1064
31
    }
1065
31
}
1066
1067
bool XMLIndexMarkImportContext_Impl::CreateMark(
1068
    Reference<beans::XPropertySet>& rPropSet,
1069
    const OUString& rServiceName)
1070
31
{
1071
31
    Reference<lang::XMultiServiceFactory>
1072
31
        xFactory(GetImport().GetModel(), UNO_QUERY);
1073
1074
31
    if( xFactory.is() )
1075
31
    {
1076
31
        Reference<beans::XPropertySet> xPropSet( xFactory->createInstance(rServiceName), UNO_QUERY );
1077
31
        if (xPropSet.is())
1078
17
            rPropSet = std::move(xPropSet);
1079
31
        return true;
1080
31
    }
1081
1082
0
    return false;
1083
31
}
1084
1085
namespace {
1086
1087
class XMLTOCMarkImportContext_Impl : public XMLIndexMarkImportContext_Impl
1088
{
1089
public:
1090
1091
    XMLTOCMarkImportContext_Impl(
1092
        SvXMLImport& rImport,
1093
        XMLHints_Impl& rHints);
1094
1095
protected:
1096
1097
    /** process outline level */
1098
    virtual void ProcessAttribute(sal_Int32 nElement,
1099
                                  const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1100
                                  Reference<beans::XPropertySet>& rPropSet) override;
1101
};
1102
1103
}
1104
1105
XMLTOCMarkImportContext_Impl::XMLTOCMarkImportContext_Impl(
1106
    SvXMLImport& rImport, XMLHints_Impl& rHints) :
1107
2
        XMLIndexMarkImportContext_Impl(rImport, rHints)
1108
2
{
1109
2
}
1110
1111
void XMLTOCMarkImportContext_Impl::ProcessAttribute(
1112
    sal_Int32 nElement,
1113
    const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1114
    Reference<beans::XPropertySet>& rPropSet)
1115
0
{
1116
0
    SAL_WARN_IF(!rPropSet.is(), "xmloff.text", "need PropertySet");
1117
1118
0
    switch (aIter.getToken())
1119
0
    {
1120
0
        case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
1121
0
        {
1122
            // outline level: set Level property
1123
0
            sal_Int32 nTmp;
1124
0
            if (::sax::Converter::convertNumber( nTmp, aIter.toView() )
1125
0
                && nTmp >= 1
1126
0
                && nTmp < GetImport().GetTextImport()->
1127
0
                                GetChapterNumbering()->getCount() )
1128
0
            {
1129
0
                rPropSet->setPropertyValue(u"Level"_ustr, uno::Any(static_cast<sal_Int16>(nTmp - 1)));
1130
0
            }
1131
            // else: value out of range -> ignore
1132
0
            break;
1133
0
        }
1134
0
        default:
1135
            // else: delegate to superclass
1136
0
            XMLIndexMarkImportContext_Impl::ProcessAttribute(
1137
0
                nElement, aIter, rPropSet);
1138
0
    }
1139
0
}
1140
1141
namespace {
1142
1143
class XMLUserIndexMarkImportContext_Impl : public XMLIndexMarkImportContext_Impl
1144
{
1145
public:
1146
1147
    XMLUserIndexMarkImportContext_Impl(
1148
        SvXMLImport& rImport,
1149
        XMLHints_Impl& rHints);
1150
1151
protected:
1152
1153
    /** process index name */
1154
    virtual void ProcessAttribute(sal_Int32 nElement,
1155
                                  const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1156
                                  Reference<beans::XPropertySet>& rPropSet) override;
1157
};
1158
1159
}
1160
1161
XMLUserIndexMarkImportContext_Impl::XMLUserIndexMarkImportContext_Impl(
1162
    SvXMLImport& rImport, XMLHints_Impl& rHints) :
1163
4
        XMLIndexMarkImportContext_Impl(rImport, rHints)
1164
4
{
1165
4
}
1166
1167
void XMLUserIndexMarkImportContext_Impl::ProcessAttribute(
1168
    sal_Int32 nElement,
1169
    const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1170
    Reference<beans::XPropertySet>& rPropSet)
1171
0
{
1172
0
    switch (aIter.getToken())
1173
0
    {
1174
0
        case XML_ELEMENT(TEXT, XML_INDEX_NAME):
1175
0
            rPropSet->setPropertyValue(u"UserIndexName"_ustr, uno::Any(aIter.toString()));
1176
0
            break;
1177
0
        case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
1178
0
        {
1179
            // outline level: set Level property
1180
0
            sal_Int32 nTmp;
1181
0
            if (::sax::Converter::convertNumber(
1182
0
                nTmp, aIter.toView(), 0,
1183
0
               GetImport().GetTextImport()->GetChapterNumbering()->getCount()))
1184
0
            {
1185
0
                rPropSet->setPropertyValue(u"Level"_ustr, uno::Any(static_cast<sal_Int16>(nTmp - 1)));
1186
0
            }
1187
            // else: value out of range -> ignore
1188
0
            break;
1189
0
        }
1190
0
        default:
1191
            // else: unknown text property: delegate to super class
1192
0
            XMLIndexMarkImportContext_Impl::ProcessAttribute(
1193
0
                nElement, aIter, rPropSet);
1194
0
    }
1195
0
}
1196
1197
namespace {
1198
1199
class XMLAlphaIndexMarkImportContext_Impl : public XMLIndexMarkImportContext_Impl
1200
{
1201
public:
1202
1203
    XMLAlphaIndexMarkImportContext_Impl(
1204
        SvXMLImport& rImport,
1205
        XMLHints_Impl& rHints);
1206
1207
protected:
1208
1209
    /** process primary + secondary keys */
1210
    virtual void ProcessAttribute(sal_Int32 nElement,
1211
                                  const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1212
                                  Reference<beans::XPropertySet>& rPropSet) override;
1213
};
1214
1215
}
1216
1217
XMLAlphaIndexMarkImportContext_Impl::XMLAlphaIndexMarkImportContext_Impl(
1218
    SvXMLImport& rImport, XMLHints_Impl& rHints) :
1219
25
        XMLIndexMarkImportContext_Impl(rImport, rHints)
1220
25
{
1221
25
}
1222
1223
void XMLAlphaIndexMarkImportContext_Impl::ProcessAttribute(
1224
    sal_Int32 nElement,
1225
    const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1226
    Reference<beans::XPropertySet>& rPropSet)
1227
0
{
1228
0
    switch (aIter.getToken())
1229
0
    {
1230
0
        case XML_ELEMENT(TEXT, XML_KEY1):
1231
0
            rPropSet->setPropertyValue(u"PrimaryKey"_ustr, uno::Any(aIter.toString()));
1232
0
            break;
1233
0
        case XML_ELEMENT(TEXT, XML_KEY2):
1234
0
            rPropSet->setPropertyValue(u"SecondaryKey"_ustr, uno::Any(aIter.toString()));
1235
0
            break;
1236
0
        case XML_ELEMENT(TEXT, XML_KEY1_PHONETIC):
1237
0
            rPropSet->setPropertyValue(u"PrimaryKeyReading"_ustr, uno::Any(aIter.toString()));
1238
0
            break;
1239
0
        case XML_ELEMENT(TEXT, XML_KEY2_PHONETIC):
1240
0
            rPropSet->setPropertyValue(u"SecondaryKeyReading"_ustr, uno::Any(aIter.toString()));
1241
0
            break;
1242
0
        case XML_ELEMENT(TEXT, XML_STRING_VALUE_PHONETIC):
1243
0
            rPropSet->setPropertyValue(u"TextReading"_ustr, uno::Any(aIter.toString()));
1244
0
            break;
1245
0
        case XML_ELEMENT(TEXT, XML_MAIN_ENTRY):
1246
0
        {
1247
0
            bool bMainEntry = false;
1248
0
            bool bTmp(false);
1249
1250
0
            if (::sax::Converter::convertBool(bTmp, aIter.toView()))
1251
0
                bMainEntry = bTmp;
1252
1253
0
            rPropSet->setPropertyValue(u"IsMainEntry"_ustr, uno::Any(bMainEntry));
1254
0
            break;
1255
0
        }
1256
0
        default:
1257
0
            XMLIndexMarkImportContext_Impl::ProcessAttribute(
1258
0
                nElement, aIter, rPropSet);
1259
0
    }
1260
0
}
1261
1262
1263
XMLImpSpanContext_Impl::XMLImpSpanContext_Impl(
1264
        SvXMLImport& rImport,
1265
        sal_Int32 /*nElement*/,
1266
        const Reference< xml::sax::XFastAttributeList > & xAttrList,
1267
        XMLHints_Impl& rHints,
1268
        bool& rIgnLeadSpace,
1269
        sal_uInt8 nSFConvFlags)
1270
38.3k
:   SvXMLImportContext( rImport )
1271
38.3k
,   m_rHints( rHints )
1272
38.3k
,   pHint( nullptr  )
1273
38.3k
,   rIgnoreLeadingSpace( rIgnLeadSpace )
1274
38.3k
,   nStarFontsConvFlags( nSFConvFlags & (CONV_FROM_STAR_BATS|CONV_FROM_STAR_MATH) )
1275
38.3k
{
1276
38.3k
    OUString aStyleName;
1277
1278
38.3k
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1279
35.7k
    {
1280
35.7k
        if( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME) )
1281
35.7k
        {
1282
35.7k
            aStyleName = aIter.toString();
1283
35.7k
            break;
1284
35.7k
        }
1285
35.7k
    }
1286
1287
38.3k
    if( !aStyleName.isEmpty() )
1288
35.7k
    {
1289
35.7k
        pHint = new XMLStyleHint_Impl( aStyleName,
1290
35.7k
                  GetImport().GetTextImport()->GetCursorAsRange()->getStart() );
1291
35.7k
        m_rHints.push_back(std::unique_ptr<XMLStyleHint_Impl>(pHint));
1292
35.7k
    }
1293
38.3k
}
1294
1295
void XMLImpSpanContext_Impl::endFastElement(sal_Int32 )
1296
35.5k
{
1297
35.5k
    if (!pHint)
1298
1.69k
        return;
1299
1300
33.8k
    Reference<XTextRange> xCrsrRange(GetImport().GetTextImport()->GetCursorAsRange());
1301
33.8k
    if (!xCrsrRange.is())
1302
0
        return; // Robust (defective file)
1303
1304
33.8k
    pHint->SetEnd(xCrsrRange->getStart());
1305
33.8k
}
1306
1307
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpSpanContext_Impl::CreateSpanContext(
1308
        SvXMLImport& rImport,
1309
        sal_Int32 nElement,
1310
        const Reference< xml::sax::XFastAttributeList > & xAttrList,
1311
        XMLHints_Impl& rHints,
1312
        bool& rIgnoreLeadingSpace,
1313
        sal_uInt8 nStarFontsConvFlags
1314
     )
1315
214k
{
1316
214k
    SvXMLImportContext *pContext = nullptr;
1317
1318
214k
    switch( nElement )
1319
214k
    {
1320
38.3k
    case XML_ELEMENT(TEXT, XML_SPAN):
1321
38.3k
        pContext = new XMLImpSpanContext_Impl( rImport, nElement,
1322
38.3k
                                               xAttrList,
1323
38.3k
                                               rHints,
1324
38.3k
                                               rIgnoreLeadingSpace
1325
38.3k
                                               ,nStarFontsConvFlags
1326
38.3k
                                             );
1327
38.3k
        break;
1328
1329
225
    case XML_ELEMENT(TEXT, XML_TAB):
1330
225
        pContext = new XMLCharContext( rImport, xAttrList,
1331
225
                                               0x0009, false );
1332
225
        rIgnoreLeadingSpace = false;
1333
225
        break;
1334
1335
140
    case XML_ELEMENT(TEXT, XML_LINE_BREAK):
1336
140
        if (xAttrList->hasAttribute(XML_ELEMENT(LO_EXT, XML_CLEAR)))
1337
0
        {
1338
0
            pContext = new SvXMLLineBreakContext(rImport, *rImport.GetTextImport());
1339
0
        }
1340
140
        else
1341
140
        {
1342
140
            pContext = new XMLCharContext(rImport, ControlCharacter::LINE_BREAK);
1343
140
        }
1344
140
        rIgnoreLeadingSpace = false;
1345
140
        break;
1346
1347
17
    case XML_ELEMENT(TEXT, XML_S):
1348
17
        pContext = new XMLCharContext( rImport, xAttrList, 0x0020, true );
1349
17
        rIgnoreLeadingSpace = false;
1350
17
        break;
1351
1352
939
    case XML_ELEMENT(TEXT, XML_A):
1353
939
    {
1354
        // test for HyperLinkURL property. If present, insert link as
1355
        // text property (StarWriter), else try to insert as text
1356
        // field (StarCalc, StarDraw, ...)
1357
939
        Reference< beans::XPropertySet > xPropSet( rImport.GetTextImport()->GetCursor(), UNO_QUERY );
1358
1359
939
        if ( xPropSet->getPropertySetInfo()->hasPropertyByName( u"HyperLinkURL"_ustr ) )
1360
240
        {
1361
240
            pContext = new XMLImpHyperlinkContext_Impl(
1362
240
                    rImport,
1363
240
                    nElement,
1364
240
                    xAttrList,
1365
240
                    rHints,
1366
240
                    rIgnoreLeadingSpace );
1367
240
        }
1368
699
        else
1369
699
        {
1370
699
            pContext = new XMLUrlFieldImportContext(rImport, *rImport.GetTextImport());
1371
            //whitespace handling like other fields
1372
699
            rIgnoreLeadingSpace = false;
1373
1374
699
        }
1375
939
        break;
1376
0
    }
1377
1378
2.56k
    case XML_ELEMENT(TEXT, XML_RUBY):
1379
2.56k
        pContext = new XMLImpRubyContext_Impl( rImport, nElement,
1380
2.56k
                                               xAttrList,
1381
2.56k
                                               rHints,
1382
2.56k
                                               rIgnoreLeadingSpace );
1383
2.56k
        break;
1384
1385
517
    case XML_ELEMENT(TEXT, XML_NOTE):
1386
517
        if (rImport.GetTextImport()->IsInFrame())
1387
0
        {
1388
            // we must not insert footnotes into text frames
1389
0
            pContext = new SvXMLImportContext( rImport );
1390
0
        }
1391
517
        else
1392
517
        {
1393
517
            pContext = new XMLFootnoteImportContext(rImport, *rImport.GetTextImport());
1394
517
        }
1395
517
        rIgnoreLeadingSpace = false;
1396
517
        break;
1397
1398
14
    case XML_ELEMENT(TEXT, XML_REFERENCE_MARK):
1399
561
    case XML_ELEMENT(TEXT, XML_BOOKMARK):
1400
569
    case XML_ELEMENT(TEXT, XML_BOOKMARK_START):
1401
877
    case XML_ELEMENT(TEXT, XML_BOOKMARK_END):
1402
877
        pContext = new XMLTextMarkImportContext(rImport, *rImport.GetTextImport(),
1403
877
                                                rHints.GetCrossRefHeadingBookmark());
1404
877
        break;
1405
1406
0
    case XML_ELEMENT(FIELD, XML_FIELDMARK):
1407
15
    case XML_ELEMENT(FIELD, XML_FIELDMARK_START):
1408
15
    case XML_ELEMENT(FIELD, XML_FIELDMARK_SEPARATOR):
1409
26
    case XML_ELEMENT(FIELD, XML_FIELDMARK_END):
1410
26
        pContext = new XMLTextMarkImportContext(rImport, *rImport.GetTextImport(),
1411
26
                                                rHints.GetCrossRefHeadingBookmark());
1412
26
        break;
1413
1414
15
    case XML_ELEMENT(TEXT, XML_REFERENCE_MARK_START):
1415
15
        pContext = new XMLStartReferenceContext_Impl( rImport,
1416
15
                                                      rHints, xAttrList );
1417
15
        break;
1418
1419
3
    case XML_ELEMENT(TEXT, XML_REFERENCE_MARK_END):
1420
3
        pContext = new XMLEndReferenceContext_Impl( rImport,
1421
3
                                                    rHints, xAttrList );
1422
3
        break;
1423
1424
17.4k
    case XML_ELEMENT(DRAW, XML_FRAME):
1425
17.4k
        {
1426
17.4k
            Reference < XTextRange > xAnchorPos =
1427
17.4k
                rImport.GetTextImport()->GetCursor()->getStart();
1428
17.4k
            XMLTextFrameContext *pTextFrameContext =
1429
17.4k
                            new XMLTextFrameContext(rImport,
1430
17.4k
                                         xAttrList,
1431
17.4k
                                         TextContentAnchorType_AS_CHARACTER );
1432
            // Remove check for text content. (#i33242#)
1433
            // Check for text content is done on the processing of the hint
1434
17.4k
            if( TextContentAnchorType_AT_CHARACTER ==
1435
17.4k
                                            pTextFrameContext->GetAnchorType() )
1436
20
            {
1437
20
                rHints.push_back(std::make_unique<XMLTextFrameHint_Impl>(
1438
20
                                    pTextFrameContext, xAnchorPos));
1439
20
            }
1440
17.4k
            pContext = pTextFrameContext;
1441
17.4k
            rIgnoreLeadingSpace = false;
1442
17.4k
        }
1443
17.4k
        break;
1444
318
    case XML_ELEMENT(DRAW, XML_A):
1445
318
        {
1446
318
            Reference < XTextRange > xAnchorPos(rImport.GetTextImport()->GetCursor()->getStart());
1447
318
            pContext =
1448
318
                new XMLTextFrameHyperlinkContext( rImport, nElement,
1449
318
                                        xAttrList,
1450
318
                                        TextContentAnchorType_AS_CHARACTER );
1451
318
            rHints.push_back(
1452
318
                std::make_unique<XMLTextFrameHint_Impl>(pContext, xAnchorPos));
1453
318
        }
1454
318
        break;
1455
1456
2
    case XML_ELEMENT(TEXT, XML_TOC_MARK):
1457
2
    case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
1458
2
        pContext = new XMLTOCMarkImportContext_Impl(
1459
2
            rImport, rHints);
1460
2
        break;
1461
1462
4
    case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
1463
4
    case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
1464
4
        pContext = new XMLUserIndexMarkImportContext_Impl(
1465
4
            rImport, rHints);
1466
4
        break;
1467
1468
25
    case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
1469
25
    case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
1470
25
        pContext = new XMLAlphaIndexMarkImportContext_Impl(
1471
25
            rImport, rHints);
1472
25
        break;
1473
1474
3
    case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
1475
4
    case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
1476
4
    case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
1477
4
        pContext = new XMLIndexMarkImportContext_Impl(
1478
4
            rImport, rHints);
1479
4
        break;
1480
1481
0
    case XML_ELEMENT(TEXT, XML_CHANGE_START):
1482
4
    case XML_ELEMENT(TEXT, XML_CHANGE_END):
1483
4
    case XML_ELEMENT(TEXT, XML_CHANGE):
1484
4
        pContext = new XMLChangeImportContext(
1485
4
            rImport,
1486
4
            ((nElement == XML_ELEMENT(TEXT, XML_CHANGE_END))
1487
4
                ? XMLChangeImportContext::Element::END
1488
4
                : (nElement == XML_ELEMENT(TEXT, XML_CHANGE_START))
1489
0
                    ? XMLChangeImportContext::Element::START
1490
0
                    : XMLChangeImportContext::Element::POINT),
1491
4
            false);
1492
4
        break;
1493
1494
4
    case  XML_ELEMENT(TEXT, XML_META):
1495
4
        pContext = new XMLMetaImportContext(rImport, nElement,
1496
4
            rHints, rIgnoreLeadingSpace );
1497
4
        break;
1498
1499
0
    case XML_ELEMENT(TEXT, XML_META_FIELD):
1500
0
        pContext = new XMLMetaFieldImportContext(rImport, nElement,
1501
0
            rHints, rIgnoreLeadingSpace );
1502
0
        break;
1503
1504
0
    case XML_ELEMENT(LO_EXT, XML_CONTENT_CONTROL):
1505
0
        pContext = new XMLContentControlContext(rImport, nElement, rHints, rIgnoreLeadingSpace);
1506
0
        break;
1507
1508
153k
    default:
1509
        // none of the above? then it's probably  a text field!
1510
153k
        pContext = XMLTextFieldImportContext::CreateTextFieldImportContext(
1511
153k
            rImport, *rImport.GetTextImport(), nElement);
1512
        // #108784# import draw elements (except control shapes in headers)
1513
153k
        if( pContext == nullptr &&
1514
51.2k
            !( rImport.GetTextImport()->IsInHeaderFooter() &&
1515
3.65k
               nElement == XML_ELEMENT(DRAW, XML_CONTROL ) ) )
1516
51.2k
        {
1517
51.2k
            Reference < XShapes > xShapes;
1518
51.2k
            SvXMLShapeContext* pShapeContext = XMLShapeImportHelper::CreateGroupChildContext(
1519
51.2k
                rImport, nElement, xAttrList, xShapes );
1520
51.2k
            pContext = pShapeContext;
1521
            // OD 2004-04-20 #i26791# - keep shape in a text frame hint to
1522
            // adjust its anchor position, if it's at-character anchored
1523
51.2k
            Reference < XTextRange > xAnchorPos =
1524
51.2k
                rImport.GetTextImport()->GetCursor()->getStart();
1525
51.2k
            rHints.push_back(
1526
51.2k
                std::make_unique<XMLDrawHint_Impl>(pShapeContext, xAnchorPos));
1527
51.2k
        }
1528
        // Behind fields, shapes and any unknown content blanks aren't ignored
1529
153k
        rIgnoreLeadingSpace = false;
1530
214k
    }
1531
1532
214k
    if (!pContext)
1533
214k
        XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
1534
214k
    return pContext;
1535
214k
}
1536
1537
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpSpanContext_Impl::createFastChildContext(
1538
    sal_Int32 nElement,
1539
    const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
1540
43.8k
{
1541
43.8k
    return CreateSpanContext( GetImport(), nElement, xAttrList,
1542
43.8k
                               m_rHints, rIgnoreLeadingSpace
1543
43.8k
                               ,nStarFontsConvFlags
1544
43.8k
                             );
1545
43.8k
}
1546
1547
void XMLImpSpanContext_Impl::characters( const OUString& rChars )
1548
67.3k
{
1549
67.3k
    OUString sStyleName;
1550
67.3k
    if( pHint )
1551
38.0k
        sStyleName = pHint->GetStyleName();
1552
67.3k
    OUString sChars =
1553
67.3k
        GetImport().GetTextImport()->ConvertStarFonts( rChars, sStyleName,
1554
67.3k
                                                       nStarFontsConvFlags,
1555
67.3k
                                                       false, GetImport() );
1556
67.3k
    GetImport().GetTextImport()->InsertString( sChars, rIgnoreLeadingSpace );
1557
67.3k
}
1558
1559
1560
XMLParaContext::XMLParaContext(
1561
        SvXMLImport& rImport,
1562
        sal_Int32 nElement,
1563
        const Reference< xml::sax::XFastAttributeList > & xAttrList ) :
1564
322k
    SvXMLImportContext( rImport ),
1565
322k
    xStart( rImport.GetTextImport()->GetCursorAsRange()->getStart() ),
1566
322k
    m_bHaveAbout(false),
1567
322k
    nOutlineLevel( (nElement & TOKEN_MASK) == XML_H ? 1 : -1 ),
1568
    // Lost outline numbering in master document (#i73509#)
1569
322k
    mbOutlineLevelAttrFound( false ),
1570
322k
    mbOutlineContentVisible(true),
1571
322k
    bIgnoreLeadingSpace( true ),
1572
322k
    bHeading( (nElement & TOKEN_MASK) == XML_H ),
1573
322k
    bIsListHeader( false ),
1574
322k
    bIsRestart (false),
1575
322k
    nStartValue(0),
1576
322k
    nStarFontsConvFlags( 0 )
1577
322k
{
1578
322k
    bool bHaveXmlId( false );
1579
322k
    OUString aCondStyleName;
1580
1581
322k
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1582
86.0k
    {
1583
86.0k
        switch( aIter.getToken() )
1584
86.0k
        {
1585
8.23k
        case XML_ELEMENT(XML, XML_ID):
1586
8.23k
            m_sXmlId = aIter.toString();
1587
8.23k
            bHaveXmlId = true;
1588
8.23k
            break;
1589
0
        case XML_ELEMENT(XHTML, XML_ABOUT):
1590
0
            m_sAbout = aIter.toString();
1591
0
            m_bHaveAbout = true;
1592
0
            break;
1593
0
        case XML_ELEMENT(XHTML, XML_PROPERTY):
1594
0
            m_sProperty = aIter.toString();
1595
0
            break;
1596
0
        case XML_ELEMENT(XHTML, XML_CONTENT):
1597
0
            m_sContent = aIter.toString();
1598
0
            break;
1599
0
        case XML_ELEMENT(XHTML, XML_DATATYPE):
1600
0
            m_sDatatype = aIter.toString();
1601
0
            break;
1602
0
        case XML_ELEMENT(TEXT, XML_ID):
1603
0
            if (!bHaveXmlId) { m_sXmlId = aIter.toString(); }
1604
0
            break;
1605
76.9k
        case XML_ELEMENT(TEXT, XML_STYLE_NAME):
1606
76.9k
            sStyleName = aIter.toString();
1607
76.9k
            break;
1608
0
        case XML_ELEMENT(TEXT, XML_COND_STYLE_NAME):
1609
0
            aCondStyleName = aIter.toString();
1610
0
            break;
1611
664
        case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
1612
664
            {
1613
664
                sal_Int32 nTmp = aIter.toInt32();
1614
664
                if( nTmp > 0 )
1615
658
                {
1616
658
                    if( nTmp > 127 )
1617
72
                        nTmp = 127;
1618
658
                    nOutlineLevel = static_cast<sal_Int8>(nTmp);
1619
658
                }
1620
                // Lost outline numbering in master document (#i73509#)
1621
664
                mbOutlineLevelAttrFound = true;
1622
664
            }
1623
664
            break;
1624
0
        case XML_ELEMENT(LO_EXT, XML_OUTLINE_CONTENT_VISIBLE):
1625
0
            {
1626
0
                bool bBool(false);
1627
0
                if (::sax::Converter::convertBool(bBool, aIter.toView()))
1628
0
                    mbOutlineContentVisible = bBool;
1629
0
            }
1630
0
            break;
1631
0
        case XML_ELEMENT(TEXT, XML_IS_LIST_HEADER):
1632
0
            {
1633
0
                bool bBool(false);
1634
0
                if (::sax::Converter::convertBool(bBool, aIter.toView()))
1635
0
                    bIsListHeader = bBool;
1636
0
            }
1637
0
            break;
1638
0
        case XML_ELEMENT(TEXT, XML_RESTART_NUMBERING):
1639
0
            {
1640
0
                bool bBool(false);
1641
0
                if (::sax::Converter::convertBool(bBool, aIter.toView()))
1642
0
                    bIsRestart = bBool;
1643
0
            }
1644
0
            break;
1645
0
        case XML_ELEMENT(TEXT, XML_START_VALUE):
1646
0
            {
1647
0
                nStartValue = sal::static_int_cast< sal_Int16 >(aIter.toInt32());
1648
0
            }
1649
0
            break;
1650
0
        case XML_ELEMENT(LO_EXT, XML_MARKER_STYLE_NAME):
1651
0
            if (auto pStyle = rImport.GetTextImport()->FindAutoCharStyle(aIter.toString()))
1652
0
                m_aMarkerStyleName = pStyle->GetAutoName();
1653
0
            break;
1654
222
        default:
1655
222
            XMLOFF_WARN_UNKNOWN("xmloff", aIter);
1656
86.0k
        }
1657
86.0k
    }
1658
1659
322k
    if( !aCondStyleName.isEmpty() )
1660
0
        sStyleName = aCondStyleName;
1661
322k
}
1662
1663
void XMLParaContext::endFastElement(sal_Int32 )
1664
311k
{
1665
311k
    rtl::Reference < XMLTextImportHelper > xTxtImport(
1666
311k
        GetImport().GetTextImport());
1667
311k
    Reference<XTextRange> xEnd;
1668
311k
    try
1669
311k
    {
1670
311k
        Reference<XTextRange> const xCrsrRange(xTxtImport->GetCursorAsRange());
1671
311k
        if (!xCrsrRange.is())
1672
0
            return; // Robust (defective file)
1673
311k
        xEnd = xCrsrRange->getStart();
1674
311k
    }
1675
311k
    catch (uno::Exception const&)
1676
311k
    {
1677
0
        SAL_INFO("xmloff.text", "XMLParaContext: cursor disposed?");
1678
0
        return;
1679
0
    }
1680
1681
    // if we have an id set for this paragraph, get a cursor for this
1682
    // paragraph and register it with the given identifier
1683
    // FIXME: this is just temporary, and should be removed when
1684
    // EditEngine paragraphs implement XMetadatable!
1685
311k
    if (!m_sXmlId.isEmpty())
1686
8.21k
    {
1687
8.21k
        Reference < XTextCursor > xIdCursor( xTxtImport->GetText()->createTextCursorByRange( xStart ) );
1688
8.21k
        if( xIdCursor.is() )
1689
8.19k
        {
1690
8.19k
            xIdCursor->gotoRange( xEnd, true );
1691
8.19k
            GetImport().getInterfaceToIdentifierMapper().registerReference(
1692
8.19k
                m_sXmlId, Reference<XInterface>( xIdCursor, UNO_QUERY ));
1693
8.19k
        }
1694
8.21k
    }
1695
1696
    // insert a paragraph break
1697
311k
    xTxtImport->InsertControlCharacter( ControlCharacter::APPEND_PARAGRAPH );
1698
1699
    // create a cursor that select the whole last paragraph
1700
311k
    Reference < XTextCursor > xAttrCursor;
1701
311k
    try {
1702
311k
        xAttrCursor = xTxtImport->GetText()->createTextCursorByRange( xStart );
1703
311k
        if( !xAttrCursor.is() )
1704
278
            return; // Robust (defective file)
1705
311k
    } catch (const uno::Exception &) {
1706
        // createTextCursorByRange() likes to throw runtime exception, even
1707
        // though it just means 'we were unable to create the cursor'
1708
0
        return;
1709
0
    }
1710
311k
    xAttrCursor->gotoRange( xEnd, true );
1711
1712
    // xml:id for RDF metadata
1713
311k
    if (!m_sXmlId.isEmpty() || m_bHaveAbout || !m_sProperty.isEmpty())
1714
8.19k
    {
1715
8.19k
        try {
1716
8.19k
            const uno::Reference<container::XEnumerationAccess> xEA
1717
8.19k
                (xAttrCursor, uno::UNO_QUERY_THROW);
1718
8.19k
            const uno::Reference<container::XEnumeration> xEnum(
1719
8.19k
                xEA->createEnumeration(), uno::UNO_SET_THROW);
1720
8.19k
            SAL_WARN_IF(!xEnum->hasMoreElements(), "xmloff.text", "xml:id: no paragraph?");
1721
8.19k
            if (xEnum->hasMoreElements()) {
1722
6.44k
                uno::Reference<rdf::XMetadatable> xMeta;
1723
6.44k
                xEnum->nextElement() >>= xMeta;
1724
6.44k
                SAL_WARN_IF(!xMeta.is(), "xmloff.text", "xml:id: not XMetadatable");
1725
6.44k
                GetImport().SetXmlId(xMeta, m_sXmlId);
1726
6.44k
                if (m_bHaveAbout)
1727
0
                {
1728
0
                    GetImport().AddRDFa(xMeta,
1729
0
                        m_sAbout, m_sProperty, m_sContent, m_sDatatype);
1730
0
                }
1731
6.44k
                SAL_WARN_IF(xEnum->hasMoreElements(), "xmloff.text", "xml:id: > 1 paragraph?");
1732
6.44k
            }
1733
8.19k
        } catch (const uno::Exception &) {
1734
1.75k
            SAL_INFO("xmloff.text", "XMLParaContext::~XMLParaContext: exception");
1735
1.75k
        }
1736
8.19k
    }
1737
1738
311k
    OUString const sCellParaStyleName(xTxtImport->GetCellParaStyleDefault());
1739
311k
    if( !sCellParaStyleName.isEmpty() )
1740
2.84k
    {
1741
        /* Suppress handling of outline and list attributes,
1742
           because of side effects of method <SetStyleAndAttrs(..)> (#i80724#)
1743
        */
1744
2.84k
        xTxtImport->SetStyleAndAttrs( GetImport(), xAttrCursor,
1745
2.84k
                                      sCellParaStyleName,
1746
2.84k
                                      true,
1747
2.84k
                                      false, -1, // suppress outline handling
1748
2.84k
                                      false );   // suppress list attributes handling
1749
2.84k
    }
1750
1751
    // #103445# for headings without style name, find the proper style
1752
311k
    if( bHeading && sStyleName.isEmpty() )
1753
194k
        xTxtImport->FindOutlineStyleName( sStyleName, nOutlineLevel );
1754
1755
    // set style and hard attributes at the previous paragraph
1756
    // Add parameter <mbOutlineLevelAttrFound> (#i73509#)
1757
311k
    sStyleName = xTxtImport->SetStyleAndAttrs( GetImport(), xAttrCursor,
1758
311k
                                               sStyleName,
1759
311k
                                               true,
1760
311k
                                               mbOutlineLevelAttrFound,
1761
311k
                                               bHeading ? nOutlineLevel : -1,
1762
311k
                                               true,
1763
311k
                                               mbOutlineContentVisible);
1764
1765
311k
    if (m_aMarkerStyleName.hasValue())
1766
0
    {
1767
0
        if (auto xPropSet = xStart.query<css::beans::XPropertySet>())
1768
0
        {
1769
0
            try
1770
0
            {
1771
0
                xPropSet->setPropertyValue(u"ListAutoFormat"_ustr, m_aMarkerStyleName);
1772
0
            }
1773
0
            catch (const css::beans::UnknownPropertyException&)
1774
0
            {
1775
                // no problem
1776
0
            }
1777
0
        }
1778
0
    }
1779
1780
    // handle list style header
1781
311k
    if (bHeading && (bIsListHeader || bIsRestart))
1782
0
    {
1783
0
        Reference<XPropertySet> xPropSet( xAttrCursor, UNO_QUERY );
1784
1785
0
        if (xPropSet.is())
1786
0
        {
1787
0
            if (bIsListHeader)
1788
0
            {
1789
0
                OUString sNumberingIsNumber
1790
0
                    (u"NumberingIsNumber"_ustr);
1791
0
                if(xPropSet->getPropertySetInfo()->
1792
0
                   hasPropertyByName(sNumberingIsNumber))
1793
0
                {
1794
0
                    xPropSet->setPropertyValue
1795
0
                        (sNumberingIsNumber, Any( false ) );
1796
0
                }
1797
0
            }
1798
0
            if (bIsRestart)
1799
0
            {
1800
0
                OUString sParaIsNumberingRestart
1801
0
                    (u"ParaIsNumberingRestart"_ustr);
1802
0
                OUString sNumberingStartValue
1803
0
                    (u"NumberingStartValue"_ustr);
1804
0
                if (xPropSet->getPropertySetInfo()->
1805
0
                    hasPropertyByName(sParaIsNumberingRestart))
1806
0
                {
1807
0
                    xPropSet->setPropertyValue
1808
0
                        (sParaIsNumberingRestart, Any(true));
1809
0
                }
1810
1811
0
                if (xPropSet->getPropertySetInfo()->
1812
0
                    hasPropertyByName(sNumberingStartValue))
1813
0
                {
1814
0
                    xPropSet->setPropertyValue
1815
0
                        (sNumberingStartValue, Any(nStartValue));
1816
0
                }
1817
0
            }
1818
1819
0
        }
1820
0
    }
1821
1822
311k
    if (m_oHints)
1823
68.4k
    {
1824
68.4k
        bool bEmptyHints = false;
1825
68.4k
        if (auto xCompare = xTxtImport->GetText().query<text::XTextRangeCompare>())
1826
45.1k
        {
1827
45.1k
            try
1828
45.1k
            {
1829
45.1k
                for (const auto& pHint : m_oHints->GetHints())
1830
39.6k
                {
1831
39.6k
                    if (xCompare->compareRegionStarts(pHint->GetStart(), pHint->GetEnd()) == 0)
1832
13.2k
                    {
1833
13.2k
                        bEmptyHints = true;
1834
13.2k
                    }
1835
39.6k
                }
1836
45.1k
            }
1837
45.1k
            catch (const uno::Exception&)
1838
45.1k
            {
1839
0
                TOOLS_WARN_EXCEPTION("xmloff.text", "");
1840
0
            }
1841
45.1k
        }
1842
68.4k
        bool bSetNoFormatAttr = false;
1843
68.4k
        uno::Reference<beans::XPropertySet> xCursorProps(xAttrCursor, uno::UNO_QUERY);
1844
68.4k
        if (bEmptyHints || m_aMarkerStyleName.hasValue())
1845
9.30k
        {
1846
            // We have at least one empty hint, then make try to ask the cursor to not upgrade our character
1847
            // attributes to paragraph-level formatting, which would lead to incorrect rendering.
1848
9.30k
            uno::Reference<beans::XPropertySetInfo> xCursorPropsInfo = xCursorProps->getPropertySetInfo();
1849
9.30k
            bSetNoFormatAttr = xCursorPropsInfo->hasPropertyByName(u"NoFormatAttr"_ustr);
1850
9.30k
        }
1851
68.4k
        if (bSetNoFormatAttr)
1852
1.79k
        {
1853
1.79k
            xCursorProps->setPropertyValue(u"NoFormatAttr"_ustr, uno::Any(true));
1854
1.79k
        }
1855
68.4k
        for (const auto & i : m_oHints->GetHints())
1856
51.8k
        {
1857
51.8k
            XMLHint_Impl *const pHint = i.get();
1858
51.8k
            xAttrCursor->gotoRange( pHint->GetStart(), false );
1859
51.8k
            xAttrCursor->gotoRange( pHint->GetEnd(), true );
1860
51.8k
            switch( pHint->GetType() )
1861
51.8k
            {
1862
33.6k
            case XMLHintType::XML_HINT_STYLE:
1863
33.6k
                {
1864
33.6k
                    const OUString& rStyleName =
1865
33.6k
                            static_cast<XMLStyleHint_Impl *>(pHint)->GetStyleName();
1866
33.6k
                    if( !rStyleName.isEmpty() )
1867
33.6k
                        xTxtImport->SetStyleAndAttrs( GetImport(),
1868
33.6k
                                                      xAttrCursor, rStyleName,
1869
33.6k
                                                      false );
1870
33.6k
                }
1871
33.6k
                break;
1872
3
            case XMLHintType::XML_HINT_REFERENCE:
1873
3
                {
1874
3
                    const OUString& rRefName =
1875
3
                            static_cast<XMLReferenceHint_Impl *>(pHint)->GetRefName();
1876
3
                    if( !rRefName.isEmpty() )
1877
3
                    {
1878
3
                        if( !pHint->GetEnd().is() )
1879
0
                            pHint->SetEnd(xEnd);
1880
1881
                        // reference name uses rStyleName member
1882
                        // borrow from XMLTextMarkImportContext
1883
3
                        XMLTextMarkImportContext::CreateAndInsertMark(
1884
3
                            GetImport(),
1885
3
                            u"com.sun.star.text.ReferenceMark"_ustr,
1886
3
                            rRefName,
1887
3
                            xAttrCursor);
1888
3
                    }
1889
3
                }
1890
3
                break;
1891
0
            case XMLHintType::XML_HINT_HYPERLINK:
1892
0
                {
1893
0
                    const XMLHyperlinkHint_Impl *pHHint =
1894
0
                        static_cast<const XMLHyperlinkHint_Impl *>(pHint);
1895
0
                    xTxtImport->SetHyperlink( GetImport(),
1896
0
                                              xAttrCursor,
1897
0
                                              pHHint->GetHRef(),
1898
0
                                              pHHint->GetName(),
1899
0
                                              pHHint->GetTargetFrameName(),
1900
0
                                              pHHint->GetStyleName(),
1901
0
                                              pHHint->GetVisitedStyleName(),
1902
0
                                              pHHint->GetEventsContext() );
1903
0
                }
1904
0
                break;
1905
4
            case XMLHintType::XML_HINT_INDEX_MARK:
1906
4
                {
1907
4
                    Reference<beans::XPropertySet> xMark(
1908
4
                        static_cast<const XMLIndexMarkHint_Impl *>(pHint)->GetMark());
1909
4
                    Reference<XTextContent> xContent(xMark, UNO_QUERY);
1910
4
                    try
1911
4
                    {
1912
4
                        xTxtImport->GetText()->insertTextContent(
1913
4
                            xAttrCursor, xContent, true );
1914
4
                    }
1915
4
                    catch (uno::RuntimeException const&)
1916
4
                    {
1917
4
                        TOOLS_INFO_EXCEPTION("xmloff.text", "could not insert index mark, presumably in editengine text");
1918
4
                    }
1919
4
                }
1920
4
                break;
1921
4
            case XMLHintType::XML_HINT_TEXT_FRAME:
1922
3
                {
1923
3
                    const XMLTextFrameHint_Impl *pFHint =
1924
3
                        static_cast<const XMLTextFrameHint_Impl *>(pHint);
1925
                    // Check for text content (#i33242#)
1926
3
                    Reference < XTextContent > xTextContent =
1927
3
                                                    pFHint->GetTextContent();
1928
3
                    if ( xTextContent.is() )
1929
3
                    {
1930
                        /* Core impl. of the unification of drawing objects and
1931
                           Writer fly frames (#i26791#)
1932
                        */
1933
3
                        if ( pFHint->IsBoundAtChar() )
1934
3
                        {
1935
3
                            xTextContent->attach( xAttrCursor );
1936
3
                        }
1937
3
                    }
1938
                    /* Consider, that hint can also contain a shape -
1939
                       e.g. drawing object of type 'Text'. (#i33242#)
1940
                    */
1941
0
                    else
1942
0
                    {
1943
0
                        Reference < XShape > xShape = pFHint->GetShape();
1944
0
                        if ( xShape.is() )
1945
0
                        {
1946
                            // determine anchor type
1947
0
                            Reference < XPropertySet > xPropSet( xShape, UNO_QUERY );
1948
0
                            TextContentAnchorType eAnchorType =
1949
0
                                            TextContentAnchorType_AT_PARAGRAPH;
1950
0
                            {
1951
0
                                Any aAny = xPropSet->getPropertyValue( u"AnchorType"_ustr );
1952
0
                                aAny >>= eAnchorType;
1953
0
                            }
1954
0
                            if ( TextContentAnchorType_AT_CHARACTER == eAnchorType )
1955
0
                            {
1956
                                // set anchor position for at-character anchored objects
1957
0
                                xPropSet->setPropertyValue(u"TextRange"_ustr, Any(xAttrCursor));
1958
0
                            }
1959
0
                        }
1960
0
                    }
1961
3
                }
1962
3
                break;
1963
            /* Core impl. of the unification of drawing objects and
1964
               Writer fly frames (#i26791#)
1965
            */
1966
18.1k
            case XMLHintType::XML_HINT_DRAW:
1967
18.1k
                {
1968
18.1k
                    const XMLDrawHint_Impl *pDHint =
1969
18.1k
                        static_cast<const XMLDrawHint_Impl*>(pHint);
1970
                    // Improvement: hint directly provides the shape. (#i33242#)
1971
18.1k
                    const Reference < XShape >& xShape = pDHint->GetShape();
1972
18.1k
                    if ( xShape.is() )
1973
1.36k
                    {
1974
                        // determine anchor type
1975
1.36k
                        Reference < XPropertySet > xPropSet( xShape, UNO_QUERY );
1976
1.36k
                        TextContentAnchorType eAnchorType = TextContentAnchorType_AT_PARAGRAPH;
1977
1.36k
                        {
1978
1.36k
                            Any aAny = xPropSet->getPropertyValue( u"AnchorType"_ustr );
1979
1.36k
                            aAny >>= eAnchorType;
1980
1.36k
                        }
1981
1.36k
                        if ( TextContentAnchorType_AT_CHARACTER == eAnchorType )
1982
4
                        {
1983
                            // set anchor position for at-character anchored objects
1984
4
                            xPropSet->setPropertyValue(u"TextRange"_ustr, Any(xAttrCursor));
1985
4
                        }
1986
1.36k
                    }
1987
18.1k
                }
1988
18.1k
                break;
1989
0
            default:
1990
0
                SAL_WARN( "xmloff.text", "What's this" );
1991
0
                break;
1992
51.8k
            }
1993
51.8k
        }
1994
68.4k
        if (bSetNoFormatAttr)
1995
1.79k
        {
1996
1.79k
            xCursorProps->setPropertyValue(u"NoFormatAttr"_ustr, uno::Any(false));
1997
1.79k
        }
1998
68.4k
    }
1999
311k
    m_oHints.reset();
2000
311k
}
2001
2002
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLParaContext::createFastChildContext(
2003
    sal_Int32 nElement,
2004
    const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
2005
168k
{
2006
168k
    if (!m_oHints)
2007
78.2k
        m_oHints.emplace();
2008
168k
    return XMLImpSpanContext_Impl::CreateSpanContext(
2009
168k
                                GetImport(), nElement, xAttrList,
2010
168k
                                *m_oHints, bIgnoreLeadingSpace,
2011
168k
                                nStarFontsConvFlags);
2012
168k
}
2013
2014
void XMLParaContext::characters( const OUString& rChars )
2015
210k
{
2016
210k
    OUString sChars =
2017
210k
        GetImport().GetTextImport()->ConvertStarFonts( rChars, sStyleName,
2018
210k
                                                       nStarFontsConvFlags,
2019
210k
                                                       true, GetImport() );
2020
210k
    GetImport().GetTextImport()->InsertString( sChars, bIgnoreLeadingSpace );
2021
210k
}
2022
2023
2024
XMLNumberedParaContext::XMLNumberedParaContext(
2025
        SvXMLImport& i_rImport,
2026
        sal_Int32 /*nElement*/,
2027
        const Reference< xml::sax::XFastAttributeList > & xAttrList ) :
2028
15.7k
    SvXMLImportContext( i_rImport ),
2029
15.7k
    m_Level(0),
2030
15.7k
    m_StartValue(-1)
2031
15.7k
{
2032
15.7k
    OUString StyleName;
2033
2034
15.7k
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
2035
0
    {
2036
0
        switch( aIter.getToken() )
2037
0
        {
2038
0
            case XML_ELEMENT(XML, XML_ID):
2039
//FIXME: there is no UNO API for lists
2040
0
                break;
2041
0
            case XML_ELEMENT(TEXT, XML_LIST_ID):
2042
0
                m_ListId = aIter.toString();
2043
0
                break;
2044
0
            case XML_ELEMENT(TEXT, XML_LEVEL):
2045
0
                {
2046
0
                    sal_Int32 nTmp = aIter.toInt32();
2047
0
                    if ( nTmp >= 1 && nTmp <= SHRT_MAX ) {
2048
0
                        m_Level = static_cast<sal_uInt16>(nTmp) - 1;
2049
0
                    }
2050
0
                }
2051
0
                break;
2052
0
            case XML_ELEMENT(TEXT, XML_STYLE_NAME):
2053
0
                StyleName = aIter.toString();
2054
0
                break;
2055
0
            case XML_ELEMENT(TEXT, XML_CONTINUE_NUMBERING):
2056
                // this attribute is deprecated
2057
//                ContinueNumbering = IsXMLToken(sValue, XML_TRUE);
2058
0
                break;
2059
0
            case XML_ELEMENT(TEXT, XML_START_VALUE):
2060
0
                {
2061
0
                    sal_Int32 nTmp = aIter.toInt32();
2062
0
                    if ( nTmp >= 0 && nTmp <= SHRT_MAX ) {
2063
0
                        m_StartValue = static_cast<sal_Int16>(nTmp);
2064
0
                    }
2065
0
                }
2066
0
                break;
2067
0
            default:
2068
0
                XMLOFF_WARN_UNKNOWN("xmloff", aIter);
2069
0
        }
2070
0
    }
2071
2072
15.7k
    XMLTextListsHelper& rTextListsHelper(
2073
15.7k
        i_rImport.GetTextImport()->GetTextListHelper() );
2074
15.7k
    if (m_ListId.isEmpty())
2075
15.7k
    {
2076
15.7k
        SAL_WARN_IF(0 <= i_rImport.GetODFVersion().compareTo(u"1.2"), "xmloff.text", "invalid numbered-paragraph: no list-id (1.2)");
2077
15.7k
        m_ListId = rTextListsHelper.GetNumberedParagraphListId(m_Level,
2078
15.7k
            StyleName);
2079
15.7k
        SAL_WARN_IF(m_ListId.isEmpty(), "xmloff.text", "numbered-paragraph: no ListId");
2080
15.7k
        if (m_ListId.isEmpty()) {
2081
0
            return;
2082
0
        }
2083
15.7k
    }
2084
15.7k
    m_xNumRules = rTextListsHelper.EnsureNumberedParagraph( i_rImport,
2085
15.7k
        m_ListId, m_Level, StyleName);
2086
2087
15.7k
    SAL_WARN_IF(!m_xNumRules.is(), "xmloff.text", "numbered-paragraph: no NumRules");
2088
2089
15.7k
    i_rImport.GetTextImport()->GetTextListHelper().PushListContext( this );
2090
15.7k
}
2091
2092
void XMLNumberedParaContext::endFastElement(sal_Int32 )
2093
15.0k
{
2094
15.0k
    if (!m_ListId.isEmpty()) {
2095
15.0k
        GetImport().GetTextImport()->PopListContext();
2096
15.0k
    }
2097
15.0k
}
2098
2099
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLNumberedParaContext::createFastChildContext(
2100
    sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
2101
68.6k
{
2102
68.6k
    switch (nElement)
2103
68.6k
    {
2104
65.8k
        case XML_ELEMENT(TEXT, XML_H):
2105
65.8k
        case XML_ELEMENT(LO_EXT, XML_H):
2106
66.4k
        case XML_ELEMENT(TEXT, XML_P):
2107
66.4k
        case XML_ELEMENT(LO_EXT, XML_P):
2108
66.4k
            return new XMLParaContext( GetImport(), nElement, xAttrList );
2109
2.18k
        default:
2110
2.18k
            XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
2111
68.6k
    }
2112
2113
2.18k
    return nullptr;
2114
68.6k
}
2115
2116
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */