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/XMLFootnoteImportContext.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 "XMLFootnoteImportContext.hxx"
21
22
#include <comphelper/diagnose_ex.hxx>
23
#include <rtl/ustring.hxx>
24
#include <sal/log.hxx>
25
#include <xmloff/xmlimp.hxx>
26
#include <xmloff/txtimp.hxx>
27
#include <xmloff/xmlnamespace.hxx>
28
#include <xmloff/xmltoken.hxx>
29
30
#include "XMLFootnoteBodyImportContext.hxx"
31
32
#include <com/sun/star/frame/XModel.hpp>
33
#include <com/sun/star/text/XTextContent.hpp>
34
#include <com/sun/star/beans/XPropertySet.hpp>
35
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
36
#include <com/sun/star/text/XFootnote.hpp>
37
38
39
using namespace ::com::sun::star::uno;
40
using namespace ::com::sun::star::text;
41
using namespace ::com::sun::star::lang;
42
using namespace ::com::sun::star::beans;
43
using namespace ::com::sun::star::xml::sax;
44
using namespace ::xmloff::token;
45
46
XMLFootnoteImportContext::XMLFootnoteImportContext(
47
    SvXMLImport& rImport,
48
    XMLTextImportHelper& rHlp )
49
517
:   SvXMLImportContext(rImport)
50
517
,   mbListContextPushed(false)
51
517
,   rHelper(rHlp)
52
517
{
53
517
}
54
55
void XMLFootnoteImportContext::startFastElement(
56
    sal_Int32 /*nElement*/,
57
    const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
58
517
{
59
    // create footnote
60
517
    Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),
61
517
                                             UNO_QUERY);
62
517
    if( !xFactory.is() )
63
0
        return;
64
65
    // create endnote or footnote
66
517
    bool bIsEndnote = false;
67
517
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
68
982
    {
69
982
        if( aIter.getToken() == XML_ELEMENT(TEXT, XML_NOTE_CLASS) )
70
494
        {
71
494
            if( IsXMLToken( aIter, XML_ENDNOTE ) )
72
28
                bIsEndnote = true;
73
494
            break;
74
494
        }
75
982
    }
76
77
517
    Reference<XInterface> xIfc = xFactory->createInstance(
78
517
        bIsEndnote ?
79
28
        u"com.sun.star.text.Endnote"_ustr :
80
517
        u"com.sun.star.text.Footnote"_ustr );
81
82
    // attach footnote to document
83
517
    Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
84
517
    rHelper.InsertTextContent(xTextContent);
85
86
    // process id attribute
87
517
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
88
507
    {
89
507
        if( aIter.getToken() == XML_ELEMENT(TEXT, XML_ID) )
90
488
        {
91
            // get ID ...
92
488
            Reference<XPropertySet> xPropertySet(xTextContent, UNO_QUERY);
93
488
            Any aAny =xPropertySet->getPropertyValue(u"ReferenceId"_ustr);
94
488
            sal_Int16 nID = 0;
95
488
            aAny >>= nID;
96
97
            // ... and insert into map
98
488
            rHelper.InsertFootnoteID( aIter.toString(), nID);
99
488
            break;
100
488
        }
101
507
    }
102
103
    // save old cursor and install new one
104
517
    xOldCursor = rHelper.GetCursor();
105
517
    Reference<XText> xText(xTextContent, UNO_QUERY);
106
517
    try
107
517
    {
108
        // May fail e.g. for a nested footnote, which is formally a valid ODF, but is not supported
109
517
        rHelper.SetCursor(xText->createTextCursor());
110
517
    }
111
517
    catch (css::uno::RuntimeException&)
112
517
    {
113
4
        TOOLS_WARN_EXCEPTION("xmloff.text", "skipping the footnote: caught");
114
4
        mbIsValid = false;
115
4
    }
116
117
    // remember old list item and block (#89891#) and reset them
118
    // for the footnote
119
514
    rHelper.PushListContext();
120
514
    mbListContextPushed = true;
121
122
    // remember footnote (for CreateChildContext)
123
514
    xFootnote.set(xTextContent, UNO_QUERY);
124
125
    // else: ignore footnote! Content will be merged into document.
126
514
}
127
128
void XMLFootnoteImportContext::endFastElement(sal_Int32 )
129
471
{
130
    // get rid of last dummy paragraph
131
471
    rHelper.DeleteParagraph();
132
133
    // reinstall old cursor
134
471
    rHelper.SetCursor(xOldCursor);
135
136
    // reinstall old list item
137
471
    if (mbListContextPushed) {
138
471
        rHelper.PopListContext();
139
471
    }
140
471
}
141
142
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLFootnoteImportContext::createFastChildContext(
143
    sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
144
1.01k
{
145
1.01k
    if (!mbIsValid)
146
8
        return {};
147
1.00k
    SvXMLImportContextRef xContext;
148
149
1.00k
    switch(nElement)
150
1.00k
    {
151
497
        case XML_ELEMENT(TEXT, XML_NOTE_CITATION):
152
497
        {
153
            // little hack: we only care for one attribute of the citation
154
            //              element. We handle that here, and then return a
155
            //              default context.
156
497
            for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
157
0
            {
158
0
                if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_LABEL) )
159
0
                    xFootnote->setLabel(aIter.toString());
160
0
            }
161
162
            // ignore content: return default context
163
497
            break;
164
0
        }
165
166
484
        case XML_ELEMENT(TEXT, XML_NOTE_BODY):
167
            // return footnote body
168
484
            xContext = new XMLFootnoteBodyImportContext(GetImport());
169
484
            break;
170
171
21
        default:
172
21
            XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
173
1.00k
    }
174
175
1.00k
    return xContext;
176
1.00k
}
177
178
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */