Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/source/uibase/config/uinums.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 <uinums.hxx>
22
23
#include <unotools/pathoptions.hxx>
24
#include <tools/stream.hxx>
25
#include <sfx2/docfile.hxx>
26
#include <svl/itemiter.hxx>
27
#include <tools/urlobj.hxx>
28
29
#include <swtypes.hxx>
30
#include <utility>
31
#include <wrtsh.hxx>
32
#include <poolfmt.hxx>
33
#include <charfmt.hxx>
34
35
using namespace ::com::sun::star;
36
37
constexpr OUString CHAPTER_FILENAME = u"chapter.cfg"_ustr;
38
39
/*
40
 Description:   Saving a rule
41
 Parameter:     rCopy -- the rule to save
42
                    nIdx -- position, where the rule is to be saved.
43
                        An old rule at that position will be overwritten.
44
*/
45
46
SwChapterNumRules::SwChapterNumRules()
47
0
{
48
0
    Init();
49
0
}
50
51
void SwChapterNumRules::Save()
52
0
{
53
0
    INetURLObject aURL;
54
0
    SvtPathOptions aPathOpt;
55
0
    aURL.SetSmartURL( aPathOpt.GetUserConfigPath() );
56
0
    aURL.setFinalSlash();
57
0
    aURL.Append(CHAPTER_FILENAME);
58
59
0
    SfxMedium aMedium( aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE );
60
0
    SvStream* pStream = aMedium.GetOutStream();
61
0
    bool bRet = (pStream && pStream->GetError() == ERRCODE_NONE);
62
0
    if (bRet)
63
0
    {
64
0
        sw::ExportStoredChapterNumberingRules(*this, *pStream,CHAPTER_FILENAME);
65
66
0
        pStream->FlushBuffer();
67
68
0
        aMedium.Commit();
69
0
    }
70
0
}
71
72
SwChapterNumRules::~SwChapterNumRules()
73
0
{
74
0
}
75
76
void  SwChapterNumRules::Init()
77
0
{
78
0
    for(auto & rpNumRule : m_pNumRules)
79
0
        rpNumRule.reset();
80
81
0
    OUString sNm(CHAPTER_FILENAME);
82
0
    SvtPathOptions aOpt;
83
0
    if( aOpt.SearchFile( sNm ))
84
0
    {
85
0
        SfxMedium aStrm( sNm, StreamMode::STD_READ );
86
0
        sw::ImportStoredChapterNumberingRules(*this, *aStrm.GetInStream(),
87
0
                CHAPTER_FILENAME);
88
0
    }
89
0
}
90
91
void SwChapterNumRules::CreateEmptyNumRule(sal_uInt16 const nIndex)
92
0
{
93
0
    assert(nIndex < nMaxRules);
94
0
    assert(!m_pNumRules[nIndex]);
95
0
    m_pNumRules[nIndex].reset(new SwNumRulesWithName);
96
0
}
97
98
void SwChapterNumRules::ApplyNumRules(const SwNumRulesWithName &rCopy, sal_uInt16 nIdx)
99
0
{
100
0
    assert(nIdx < nMaxRules);
101
0
    if( !m_pNumRules[nIdx] )
102
0
        m_pNumRules[nIdx].reset(new SwNumRulesWithName( rCopy ));
103
0
    else
104
0
        *m_pNumRules[nIdx] = rCopy;
105
0
    Save(); // store it immediately
106
0
}
107
108
SwNumRulesWithName::SwNumRulesWithName( const SwNumRule &rCopy,
109
                                        OUString aName )
110
0
    : maName(std::move(aName))
111
0
{
112
0
    for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
113
0
    {
114
0
        const SwNumFormat* pFormat = rCopy.GetNumFormat( n );
115
0
        if( pFormat )
116
0
            m_aFormats[ n ].reset(new SwNumFormatGlobal( *pFormat ));
117
0
        else
118
0
            m_aFormats[ n ].reset();
119
0
    }
120
0
}
121
122
SwNumRulesWithName::SwNumRulesWithName( const SwNumRulesWithName& rCopy )
123
0
{
124
0
    *this = rCopy;
125
0
}
126
127
SwNumRulesWithName::~SwNumRulesWithName()
128
0
{
129
0
}
130
131
SwNumRulesWithName& SwNumRulesWithName::operator=(const SwNumRulesWithName &rCopy)
132
0
{
133
0
    if( this != &rCopy )
134
0
    {
135
0
        maName = rCopy.maName;
136
0
        for( int n = 0; n < MAXLEVEL; ++n )
137
0
        {
138
0
            SwNumFormatGlobal* pFormat = rCopy.m_aFormats[ n ].get();
139
0
            if( pFormat )
140
0
                m_aFormats[ n ].reset(new SwNumFormatGlobal( *pFormat ));
141
0
            else
142
0
                m_aFormats[ n ].reset();
143
0
        }
144
0
    }
145
0
    return *this;
146
0
}
147
148
void SwNumRulesWithName::ResetNumRule(SwWrtShell& rSh, SwNumRule& rNumRule) const
149
0
{
150
    // #i89178#
151
0
    rNumRule.Reset(maName);
152
0
    rNumRule.SetAutoRule( false );
153
0
    for (sal_uInt16 n = 0; n < MAXLEVEL; ++n)
154
0
    {
155
0
        SwNumFormatGlobal* pFormat = m_aFormats[ n ].get();
156
0
        if (!pFormat)
157
0
            continue;
158
0
        rNumRule.Set(n, pFormat->MakeNumFormat(rSh));
159
0
    }
160
0
}
161
162
void SwNumRulesWithName::GetNumFormat(
163
    size_t const nIndex, SwNumFormat const*& rpNumFormat, UIName const*& rpName) const
164
0
{
165
0
    rpNumFormat = (m_aFormats[nIndex]) ? &m_aFormats[nIndex]->m_aFormat : nullptr;
166
0
    rpName = (m_aFormats[nIndex]) ? &m_aFormats[nIndex]->m_sCharFormatName : nullptr;
167
0
}
168
169
void SwNumRulesWithName::SetNumFormat(
170
        size_t const nIndex, SwNumFormat const& rNumFormat, UIName const& rName)
171
0
{
172
0
    m_aFormats[nIndex].reset( new SwNumFormatGlobal(rNumFormat) );
173
0
    m_aFormats[nIndex]->m_sCharFormatName = rName;
174
0
    m_aFormats[nIndex]->m_nCharPoolId = SwPoolFormatId::UNKNOWN;
175
0
    m_aFormats[nIndex]->m_Items.clear();
176
0
}
177
178
SwNumRulesWithName::SwNumFormatGlobal::SwNumFormatGlobal( const SwNumFormat& rFormat )
179
0
    : m_aFormat( rFormat ), m_nCharPoolId( SwPoolFormatId::UNKNOWN )
180
0
{
181
    // relative gaps?????
182
183
0
    SwCharFormat* pFormat = rFormat.GetCharFormat();
184
0
    if( !pFormat )
185
0
        return;
186
187
0
    m_sCharFormatName = pFormat->GetName();
188
0
    m_nCharPoolId = pFormat->GetPoolFormatId();
189
0
    if( pFormat->GetAttrSet().Count() )
190
0
    {
191
0
        SfxItemIter aIter( pFormat->GetAttrSet() );
192
0
        const SfxPoolItem *pCurr = aIter.GetCurItem();
193
0
        do
194
0
        {
195
0
            m_Items.push_back(std::unique_ptr<SfxPoolItem>(pCurr->Clone()));
196
0
            pCurr = aIter.NextItem();
197
0
        } while (pCurr);
198
0
    }
199
200
0
    m_aFormat.SetCharFormat( nullptr );
201
0
}
202
203
SwNumRulesWithName::SwNumFormatGlobal::SwNumFormatGlobal( const SwNumFormatGlobal& rFormat )
204
    :
205
0
    m_aFormat( rFormat.m_aFormat ),
206
0
    m_sCharFormatName( rFormat.m_sCharFormatName ),
207
0
    m_nCharPoolId( rFormat.m_nCharPoolId )
208
0
{
209
0
    for (size_t n = rFormat.m_Items.size(); n; )
210
0
    {
211
0
        m_Items.push_back(std::unique_ptr<SfxPoolItem>(rFormat.m_Items[ --n ]->Clone()));
212
0
    }
213
0
}
214
215
SwNumRulesWithName::SwNumFormatGlobal::~SwNumFormatGlobal()
216
0
{
217
0
}
218
219
SwNumFormat SwNumRulesWithName::SwNumFormatGlobal::MakeNumFormat(SwWrtShell& rSh) const
220
0
{
221
0
    SwCharFormat* pFormat = nullptr;
222
0
    if( !m_sCharFormatName.isEmpty() )
223
0
    {
224
        // at first, look for the name
225
0
        sal_uInt16 nArrLen = rSh.GetCharFormatCount();
226
0
        for( sal_uInt16 i = 1; i < nArrLen; ++i )
227
0
        {
228
0
            pFormat = &rSh.GetCharFormat( i );
229
0
            if (pFormat->GetName()==m_sCharFormatName)
230
                // exists, so leave attributes as they are!
231
0
                break;
232
0
            pFormat = nullptr;
233
0
        }
234
235
0
        if( !pFormat )
236
0
        {
237
0
            if( IsPoolUserFormat( m_nCharPoolId ) )
238
0
            {
239
0
                pFormat = rSh.MakeCharFormat( m_sCharFormatName );
240
0
                pFormat->SetAuto(false);
241
0
            }
242
0
            else
243
0
                pFormat = rSh.GetCharFormatFromPool( m_nCharPoolId );
244
245
0
            if( !pFormat->HasWriterListeners() )       // set attributes
246
0
            {
247
0
                for (size_t n = m_Items.size(); n; )
248
0
                {
249
0
                    pFormat->SetFormatAttr( *m_Items[ --n ] );
250
0
                }
251
0
            }
252
0
        }
253
0
    }
254
0
    const_cast<SwNumFormat&>(m_aFormat).SetCharFormat(pFormat);
255
0
    SwNumFormat aNew = m_aFormat;
256
0
    if (pFormat)
257
0
        const_cast<SwNumFormat&>(m_aFormat).SetCharFormat(nullptr);
258
0
    return aNew;
259
0
}
260
261
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */