Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/xoutdev/xtable.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 <memory>
21
#include <utility>
22
#include <xmlxtexp.hxx>
23
#include <xmlxtimp.hxx>
24
#include <o3tl/safeint.hxx>
25
#include <osl/diagnose.h>
26
#include <tools/urlobj.hxx>
27
#include <svx/xtable.hxx>
28
#include <tools/debug.hxx>
29
#include <stack>
30
31
using namespace com::sun::star;
32
33
XColorEntry::XColorEntry(const Color& rColor, const OUString& rName)
34
4.78k
:   XPropertyEntry(rName),
35
4.78k
    m_aColor(rColor)
36
4.78k
{
37
4.78k
}
38
39
std::unique_ptr<XPropertyEntry> XColorEntry::Clone() const
40
0
{
41
0
    return std::make_unique<XColorEntry>(m_aColor, GetName());
42
0
}
43
44
XLineEndEntry::XLineEndEntry(basegfx::B2DPolyPolygon _aB2DPolyPolygon, const OUString& rName)
45
0
:   XPropertyEntry(rName),
46
0
    m_aB2DPolyPolygon(std::move(_aB2DPolyPolygon))
47
0
{
48
0
}
49
50
XLineEndEntry::XLineEndEntry(const XLineEndEntry& rOther)
51
0
:   XPropertyEntry(rOther),
52
0
    m_aB2DPolyPolygon(rOther.m_aB2DPolyPolygon)
53
0
{
54
0
}
55
56
std::unique_ptr<XPropertyEntry> XLineEndEntry::Clone() const
57
0
{
58
0
    return std::make_unique<XLineEndEntry>(*this);
59
0
}
60
61
XDashEntry::XDashEntry(const XDash& rDash, const OUString& rName)
62
3.53k
:   XPropertyEntry(rName),
63
3.53k
    m_aDash(rDash)
64
3.53k
{
65
3.53k
}
66
67
XDashEntry::XDashEntry(const XDashEntry& rOther)
68
0
:   XPropertyEntry(rOther),
69
0
m_aDash(rOther.m_aDash)
70
0
{
71
0
}
72
73
std::unique_ptr<XPropertyEntry> XDashEntry::Clone() const
74
0
{
75
0
    return std::make_unique<XDashEntry>(*this);
76
0
}
77
78
XHatchEntry::XHatchEntry(const XHatch& rHatch, const OUString& rName)
79
993
:   XPropertyEntry(rName),
80
993
    m_aHatch(rHatch)
81
993
{
82
993
}
83
84
XHatchEntry::XHatchEntry(const XHatchEntry& rOther)
85
0
:   XPropertyEntry(rOther),
86
0
    m_aHatch(rOther.m_aHatch)
87
0
{
88
0
}
89
90
std::unique_ptr<XPropertyEntry> XHatchEntry::Clone() const
91
0
{
92
0
    return std::make_unique<XHatchEntry>(*this);
93
0
}
94
95
XGradientEntry::XGradientEntry(const basegfx::BGradient& rGradient, const OUString& rName)
96
8.00k
:   XPropertyEntry(rName),
97
8.00k
    m_aGradient(rGradient)
98
8.00k
{
99
8.00k
}
100
101
XGradientEntry::XGradientEntry(const XGradientEntry& rOther)
102
0
:   XPropertyEntry(rOther),
103
0
    m_aGradient(rOther.m_aGradient)
104
0
{
105
0
}
106
107
std::unique_ptr<XPropertyEntry> XGradientEntry::Clone() const
108
0
{
109
0
    return std::make_unique<XGradientEntry>(*this);
110
0
}
111
112
XBitmapEntry::XBitmapEntry(const GraphicObject& rGraphicObject, const OUString& rName)
113
2.20k
:   XPropertyEntry(rName),
114
2.20k
    maGraphicObject(rGraphicObject)
115
2.20k
{
116
2.20k
}
117
118
XBitmapEntry::XBitmapEntry(const XBitmapEntry& rOther)
119
0
:   XPropertyEntry(rOther),
120
0
    maGraphicObject(rOther.maGraphicObject)
121
0
{
122
0
}
123
124
std::unique_ptr<XPropertyEntry> XBitmapEntry::Clone() const
125
0
{
126
0
    return std::make_unique<XBitmapEntry>(*this);
127
0
}
128
129
XPropertyList::XPropertyList(
130
    XPropertyListType type,
131
    OUString aPath, OUString aReferer
132
989k
) : meType           ( type ),
133
989k
    maName           ( u"standard"_ustr ),
134
989k
    maPath           (std::move( aPath )),
135
989k
    maReferer        (std::move( aReferer )),
136
989k
    mbListDirty      ( true ),
137
989k
    mbEmbedInDocument( false )
138
989k
    , mbNeedsExportableList(false)
139
989k
{
140
//    fprintf (stderr, "Create type %d count %d\n", (int)meType, count++);
141
989k
}
142
143
bool XPropertyList::isValidIdx(tools::Long nIndex) const
144
152k
{
145
152k
    return (nIndex >= 0 && o3tl::make_unsigned(nIndex) < maList.size());
146
152k
}
147
148
149
XPropertyList::~XPropertyList()
150
989k
{
151
989k
}
152
153
tools::Long XPropertyList::Count() const
154
36.2k
{
155
36.2k
    if( mbListDirty )
156
4.39k
    {
157
4.39k
        if( !const_cast<XPropertyList*>(this)->Load() )
158
4.39k
            const_cast<XPropertyList*>(this)->Create();
159
4.39k
    }
160
36.2k
    return maList.size();
161
36.2k
}
162
163
XPropertyEntry* XPropertyList::Get( tools::Long nIndex ) const
164
132k
{
165
132k
    if( mbListDirty )
166
29
    {
167
29
        if( !const_cast<XPropertyList*>(this)->Load() )
168
29
            const_cast<XPropertyList*>(this)->Create();
169
29
    }
170
132k
    if (!isValidIdx(nIndex))
171
0
        return nullptr;
172
173
132k
    return maList[nIndex].get();
174
132k
}
175
176
tools::Long XPropertyList::GetIndex(std::u16string_view rName) const
177
0
{
178
0
    if( mbListDirty )
179
0
    {
180
0
        if( !const_cast<XPropertyList*>(this)->Load() )
181
0
            const_cast<XPropertyList*>(this)->Create();
182
0
    }
183
184
0
    for( tools::Long i = 0, n = maList.size(); i < n; ++i ) {
185
0
        if (rName == maList[ i ]->GetName()) {
186
0
            return i;
187
0
        }
188
0
    }
189
0
    return -1;
190
0
}
191
192
Bitmap XPropertyList::GetUiBitmap( tools::Long nIndex ) const
193
0
{
194
0
    Bitmap aRetval;
195
0
    if (!isValidIdx(nIndex))
196
0
        return aRetval;
197
198
0
    XPropertyEntry* pEntry = maList[nIndex].get();
199
0
    aRetval = pEntry->GetUiBitmap();
200
201
0
    if(aRetval.IsEmpty())
202
0
    {
203
0
        aRetval = const_cast< XPropertyList* >(this)->CreateBitmapForUI(nIndex);
204
0
        pEntry->SetUiBitmap(aRetval);
205
0
    }
206
0
    return aRetval;
207
0
}
208
209
void XPropertyList::Insert(std::unique_ptr<XPropertyEntry> pEntry, tools::Long nIndex)
210
19.5k
{
211
19.5k
    if (!pEntry)
212
0
    {
213
0
        assert(!"empty XPropertyEntry not allowed in XPropertyList");
214
0
        return;
215
0
    }
216
217
19.5k
    if (!pEntry->GetSavingAllowed())
218
0
        mbNeedsExportableList = true;
219
220
19.5k
    if (isValidIdx(nIndex)) {
221
0
        maList.insert( maList.begin()+nIndex, std::move(pEntry) );
222
19.5k
    } else {
223
19.5k
        maList.push_back( std::move(pEntry) );
224
19.5k
    }
225
19.5k
}
226
227
void XPropertyList::Replace(std::unique_ptr<XPropertyEntry> pEntry, tools::Long nIndex)
228
0
{
229
0
    if (!pEntry)
230
0
    {
231
0
        assert(!"empty XPropertyEntry not allowed in XPropertyList");
232
0
        return;
233
0
    }
234
0
    if (!isValidIdx(nIndex))
235
0
    {
236
0
        assert(!"trying to replace invalid entry in XPropertyList");
237
0
        return;
238
0
    }
239
240
0
    maList[nIndex] = std::move(pEntry);
241
0
}
242
243
void XPropertyList::Remove(tools::Long nIndex)
244
0
{
245
0
    if (!isValidIdx(nIndex))
246
0
    {
247
0
        assert(!"trying to remove invalid entry in XPropertyList");
248
0
        return;
249
0
    }
250
251
0
    maList.erase(maList.begin() + nIndex);
252
0
}
253
254
void XPropertyList::SetName( const OUString& rString )
255
17.6k
{
256
17.6k
    if(!rString.isEmpty())
257
17.6k
    {
258
17.6k
        maName = rString;
259
17.6k
    }
260
17.6k
}
261
262
bool XPropertyList::Load()
263
4.41k
{
264
4.41k
    if( mbListDirty )
265
4.41k
    {
266
4.41k
        mbListDirty = false;
267
4.41k
        std::stack<OUString> aDirs;
268
269
4.41k
        sal_Int32 nIndex = 0;
270
4.41k
        do
271
4.41k
        {
272
4.41k
            aDirs.push(maPath.getToken(0, ';', nIndex));
273
4.41k
        }
274
4.41k
        while (nIndex >= 0);
275
276
        //try all entries palette path list working back to front until one
277
        //succeeds
278
4.41k
        while (!aDirs.empty())
279
4.41k
        {
280
4.41k
            OUString aPath(aDirs.top());
281
4.41k
            aDirs.pop();
282
283
4.41k
            INetURLObject aURL(aPath);
284
285
4.41k
            if( INetProtocol::NotValid == aURL.GetProtocol() )
286
4.41k
            {
287
4.41k
                DBG_ASSERT( aPath.isEmpty(), "invalid URL" );
288
4.41k
                return false;
289
4.41k
            }
290
291
0
            aURL.Append( maName );
292
293
0
            if( aURL.getExtension().isEmpty() )
294
0
                aURL.setExtension( GetDefaultExt() );
295
296
0
            bool bRet = SvxXMLXTableImport::load(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),
297
0
                                             maReferer, uno::Reference < embed::XStorage >(),
298
0
                                             createInstance(), nullptr );
299
0
            if (bRet)
300
0
                return bRet;
301
0
        }
302
4.41k
    }
303
0
    return false;
304
4.41k
}
305
306
bool XPropertyList::LoadFrom( const uno::Reference < embed::XStorage > &xStorage,
307
                              const OUString &rURL, const OUString &rReferer )
308
17.6k
{
309
17.6k
    if( !mbListDirty )
310
0
        return false;
311
17.6k
    mbListDirty = false;
312
17.6k
    return SvxXMLXTableImport::load( rURL, rReferer, xStorage, createInstance(), &mbEmbedInDocument );
313
17.6k
}
314
315
bool XPropertyList::Save()
316
0
{
317
    //save to the last path in the palette path list
318
0
    OUString aLastDir;
319
0
    sal_Int32 nIndex = 0;
320
0
    do
321
0
    {
322
0
        aLastDir = maPath.getToken(0, ';', nIndex);
323
0
    }
324
0
    while (nIndex >= 0);
325
326
0
    INetURLObject aURL(aLastDir);
327
328
0
    if( INetProtocol::NotValid == aURL.GetProtocol() )
329
0
    {
330
0
        DBG_ASSERT( aLastDir.isEmpty(), "invalid URL" );
331
0
        return false;
332
0
    }
333
334
0
    aURL.Append( maName );
335
336
0
    if( aURL.getExtension().isEmpty() )
337
0
        aURL.setExtension( GetDefaultExt() );
338
339
0
    XPropertyListRef rExportableList = CreatePropertyList(meType, maPath, "");
340
0
    if (mbNeedsExportableList)
341
0
    {
342
0
        rExportableList->SetName(maName);
343
0
        rExportableList->SetDirty(mbListDirty);
344
0
        bool bHasUnsaveableEntry = false;
345
0
        for (const std::unique_ptr<XPropertyEntry>& rEntry : maList)
346
0
        {
347
0
            if (rEntry->GetSavingAllowed())
348
0
                rExportableList->Insert(rEntry->Clone());
349
0
            else
350
0
                bHasUnsaveableEntry = true;
351
0
        }
352
0
        if (!bHasUnsaveableEntry)
353
0
            mbNeedsExportableList = false;
354
0
    }
355
0
    css::uno::Reference<css::container::XNameContainer> xExportableNameContainer
356
0
        = mbNeedsExportableList ? rExportableList->createInstance() : createInstance();
357
358
0
    return SvxXMLXTableExportComponent::save( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
359
0
                                              xExportableNameContainer,
360
0
                                              uno::Reference< embed::XStorage >(), nullptr );
361
0
}
362
363
bool XPropertyList::SaveTo( const uno::Reference< embed::XStorage > &xStorage,
364
                            const OUString &rURL, OUString *pOptName )
365
0
{
366
0
    return SvxXMLXTableExportComponent::save( rURL, createInstance(), xStorage, pOptName );
367
0
}
368
369
XPropertyListRef XPropertyList::CreatePropertyList( XPropertyListType aType,
370
                                                    const OUString& rPath,
371
                                                    const OUString& rReferer )
372
989k
{
373
989k
    XPropertyListRef pRet;
374
375
989k
    switch (aType) {
376
156k
        case XPropertyListType::Color:
377
156k
            pRet = XPropertyListRef(new XColorList(rPath, rReferer));
378
156k
            break;
379
136k
        case XPropertyListType::LineEnd:
380
136k
            pRet = XPropertyListRef(new XLineEndList(rPath, rReferer));
381
136k
            break;
382
136k
        case XPropertyListType::Dash:
383
136k
            pRet = XPropertyListRef(new XDashList(rPath, rReferer));
384
136k
            break;
385
151k
        case XPropertyListType::Hatch:
386
151k
            pRet = XPropertyListRef(new XHatchList(rPath, rReferer));
387
151k
            break;
388
136k
        case XPropertyListType::Gradient:
389
136k
            pRet = XPropertyListRef(new XGradientList(rPath, rReferer));
390
136k
            break;
391
136k
        case XPropertyListType::Bitmap:
392
136k
            pRet = XPropertyListRef(new XBitmapList(rPath, rReferer));
393
136k
            break;
394
136k
        case XPropertyListType::Pattern:
395
136k
            pRet = XPropertyListRef(new XPatternList(rPath, rReferer));
396
136k
            break;
397
0
    default:
398
0
        OSL_FAIL("unknown xproperty type");
399
0
        break;
400
989k
    }
401
989k
    OSL_ASSERT( !pRet.is() || pRet->meType == aType );
402
403
989k
    return pRet;
404
989k
}
405
406
XPropertyListRef
407
XPropertyList::CreatePropertyListFromURL( XPropertyListType t,
408
                                          std::u16string_view rURLStr )
409
0
{
410
0
    INetURLObject aURL( rURLStr );
411
0
    INetURLObject aPathURL( aURL );
412
413
0
    aPathURL.removeSegment();
414
0
    aPathURL.removeFinalSlash();
415
416
0
    XPropertyListRef pList = XPropertyList::CreatePropertyList(
417
0
        t, aPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), u""_ustr );
418
0
    pList->SetName( aURL.getName() );
419
420
0
    return pList;
421
0
}
422
423
struct {
424
    XPropertyListType t;
425
    OUString aExt;
426
} constexpr pExtnMap[] = {
427
    { XPropertyListType::Color,    u"soc"_ustr },
428
    { XPropertyListType::LineEnd, u"soe"_ustr },
429
    { XPropertyListType::Dash,     u"sod"_ustr },
430
    { XPropertyListType::Hatch,    u"soh"_ustr },
431
    { XPropertyListType::Gradient, u"sog"_ustr },
432
    { XPropertyListType::Bitmap,   u"sob"_ustr },
433
    { XPropertyListType::Pattern,  u"sop"_ustr}
434
};
435
436
OUString XPropertyList::GetDefaultExt( XPropertyListType t )
437
48
{
438
48
    for (const auto & i : pExtnMap)
439
168
    {
440
168
        if( i.t == t )
441
48
            return i.aExt;
442
168
    }
443
0
    return OUString();
444
48
}
445
446
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */