Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/svdraw/svdotxln.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 <sal/config.h>
21
22
#include <comphelper/processfactory.hxx>
23
#include <osl/file.hxx>
24
#include <osl/thread.h>
25
#include <unotools/ucbstreamhelper.hxx>
26
#include <ucbhelper/content.hxx>
27
#include <unotools/datetime.hxx>
28
#include <svx/svdotext.hxx>
29
#include <svx/svdmodel.hxx>
30
#include <editeng/editdata.hxx>
31
#include <sfx2/lnkbase.hxx>
32
#include <sfx2/linkmgr.hxx>
33
#include <tools/urlobj.hxx>
34
#include <tools/debug.hxx>
35
#include <tools/tenccvt.hxx>
36
#include <memory>
37
38
class ImpSdrObjTextLink: public ::sfx2::SvBaseLink
39
{
40
    SdrTextObj*                 pSdrObj;
41
42
public:
43
    explicit ImpSdrObjTextLink( SdrTextObj* pObj1 )
44
0
        : ::sfx2::SvBaseLink( ::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SIMPLE_FILE ),
45
0
            pSdrObj( pObj1 )
46
0
    {}
47
48
    virtual void Closed() override;
49
    virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
50
        const OUString& rMimeType, const css::uno::Any & rValue ) override;
51
};
52
53
void ImpSdrObjTextLink::Closed()
54
0
{
55
0
    if (pSdrObj )
56
0
    {
57
        // set pLink of the object to NULL, because we are destroying the link instance now
58
0
        ImpSdrObjTextLinkUserData* pData=pSdrObj->GetLinkUserData();
59
0
        if (pData!=nullptr) pData->mpLink = nullptr;
60
0
        pSdrObj->ReleaseTextLink();
61
0
    }
62
0
    SvBaseLink::Closed();
63
0
}
64
65
66
::sfx2::SvBaseLink::UpdateResult ImpSdrObjTextLink::DataChanged(
67
    const OUString& /*rMimeType*/, const css::uno::Any & /*rValue */)
68
0
{
69
0
    bool bForceReload = false;
70
0
    SdrModel* pModel(pSdrObj ? &pSdrObj->getSdrModelFromSdrObject() : nullptr);
71
0
    sfx2::LinkManager* pLinkManager(pModel ? pModel->GetLinkManager() : nullptr);
72
73
0
    if( pLinkManager )
74
0
    {
75
0
        ImpSdrObjTextLinkUserData* pData=pSdrObj->GetLinkUserData();
76
0
        if( pData )
77
0
        {
78
0
            OUString aFile;
79
0
            OUString aFilter;
80
0
            sfx2::LinkManager::GetDisplayNames( this, nullptr,&aFile, nullptr, &aFilter );
81
82
0
            if( pData->maFileName != aFile ||
83
0
                pData->maFilterName != aFilter )
84
0
            {
85
0
                pData->maFileName = aFile;
86
0
                pData->maFilterName = aFilter;
87
0
                pSdrObj->SetChanged();
88
0
                bForceReload = true;
89
0
            }
90
0
        }
91
0
    }
92
0
    if (pSdrObj )
93
0
        pSdrObj->ReloadLinkedText( bForceReload );
94
95
0
    return SUCCESS;
96
0
}
97
98
99
ImpSdrObjTextLinkUserData::ImpSdrObjTextLinkUserData():
100
0
    SdrObjUserData(SdrInventor::Default,SDRUSERDATA_OBJTEXTLINK),
101
0
    maFileDate0( DateTime::EMPTY ),
102
0
    meCharSet(RTL_TEXTENCODING_DONTKNOW)
103
0
{
104
0
}
105
106
ImpSdrObjTextLinkUserData::~ImpSdrObjTextLinkUserData()
107
0
{
108
0
}
109
110
std::unique_ptr<SdrObjUserData> ImpSdrObjTextLinkUserData::Clone(SdrObject* ) const
111
0
{
112
0
    ImpSdrObjTextLinkUserData* pData = new ImpSdrObjTextLinkUserData;
113
0
    pData->maFileName = maFileName;
114
0
    pData->maFilterName = maFilterName;
115
0
    pData->maFileDate0 = maFileDate0;
116
0
    pData->meCharSet = meCharSet;
117
0
    pData->mpLink = nullptr;
118
0
    return std::unique_ptr<SdrObjUserData>(pData);
119
0
}
120
121
122
void SdrTextObj::SetTextLink(const OUString& rFileName, const OUString& rFilterName)
123
0
{
124
0
    rtl_TextEncoding eCharSet = osl_getThreadTextEncoding();
125
126
0
    ImpSdrObjTextLinkUserData* pData=GetLinkUserData();
127
0
    if (pData!=nullptr) {
128
0
        ReleaseTextLink();
129
0
    }
130
0
    pData=new ImpSdrObjTextLinkUserData;
131
0
    pData->maFileName = rFileName;
132
0
    pData->maFilterName = rFilterName;
133
0
    pData->meCharSet = eCharSet;
134
0
    AppendUserData(std::unique_ptr<SdrObjUserData>(pData));
135
0
    ImpRegisterLink();
136
0
}
137
138
void SdrTextObj::ReleaseTextLink()
139
0
{
140
0
    ImpDeregisterLink();
141
0
    sal_uInt16 nCount=GetUserDataCount();
142
0
    for (sal_uInt16 nNum=nCount; nNum>0;) {
143
0
        nNum--;
144
0
        SdrObjUserData* pData=GetUserData(nNum);
145
0
        if (pData->GetInventor()==SdrInventor::Default && pData->GetId()==SDRUSERDATA_OBJTEXTLINK) {
146
0
            DeleteUserData(nNum);
147
0
        }
148
0
    }
149
0
}
150
151
bool SdrTextObj::ReloadLinkedText( bool bForceLoad)
152
0
{
153
0
    ImpSdrObjTextLinkUserData*  pData = GetLinkUserData();
154
0
    bool                        bRet = true;
155
156
0
    if( pData )
157
0
    {
158
0
        DateTime                    aFileDT( DateTime::EMPTY );
159
0
        bool                        bExists = true;
160
161
0
        try
162
0
        {
163
0
            INetURLObject aURL( pData->maFileName );
164
0
            DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" );
165
166
0
            ::ucbhelper::Content aCnt( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), css::uno::Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
167
0
            css::uno::Any aAny( aCnt.getPropertyValue(u"DateModified"_ustr) );
168
0
            css::util::DateTime aDateTime;
169
170
0
            aAny >>= aDateTime;
171
0
            ::utl::typeConvert( aDateTime, aFileDT );
172
0
        }
173
0
        catch( ... )
174
0
        {
175
0
            bExists = false;
176
0
        }
177
178
0
        if( bExists )
179
0
        {
180
0
            bool bLoad = false;
181
0
            if( bForceLoad )
182
0
                bLoad = true;
183
0
            else
184
0
                bLoad = ( aFileDT > pData->maFileDate0 );
185
186
0
            if( bLoad )
187
0
            {
188
0
                bRet = LoadText( pData->maFileName, pData->meCharSet );
189
0
            }
190
191
0
            pData->maFileDate0 = aFileDT;
192
0
        }
193
0
    }
194
195
0
    return bRet;
196
0
}
197
198
bool SdrTextObj::LoadText(const OUString& rFileName, rtl_TextEncoding eCharSet)
199
0
{
200
0
    INetURLObject   aFileURL( rFileName );
201
0
    bool            bRet = false;
202
203
0
    if( aFileURL.GetProtocol() == INetProtocol::NotValid )
204
0
    {
205
0
        OUString aFileURLStr;
206
207
0
        if( osl::FileBase::getFileURLFromSystemPath( rFileName, aFileURLStr ) == osl::FileBase::E_None )
208
0
            aFileURL = INetURLObject( aFileURLStr );
209
0
        else
210
0
            aFileURL.SetSmartURL( rFileName );
211
0
    }
212
213
0
    DBG_ASSERT( aFileURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" );
214
215
0
    std::unique_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ));
216
217
0
    if( pIStm )
218
0
    {
219
0
        pIStm->SetStreamCharSet(GetSOLoadTextEncoding(eCharSet));
220
221
0
        char cRTF[5];
222
0
        cRTF[4] = 0;
223
0
        pIStm->ReadBytes(cRTF, 5);
224
225
0
        bool bRTF = cRTF[0] == '{' && cRTF[1] == '\\' && cRTF[2] == 'r' && cRTF[3] == 't' && cRTF[4] == 'f';
226
227
0
        pIStm->Seek(0);
228
229
0
        if( !pIStm->GetError() )
230
0
        {
231
0
            SetText( *pIStm, aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), bRTF ? EETextFormat::Rtf : EETextFormat::Text );
232
0
            bRet = true;
233
0
        }
234
0
    }
235
236
0
    return bRet;
237
0
}
238
239
ImpSdrObjTextLinkUserData* SdrTextObj::GetLinkUserData() const
240
2.11M
{
241
2.11M
    sal_uInt16 nCount=GetUserDataCount();
242
3.48M
    for (sal_uInt16 nNum=nCount; nNum>0;) {
243
1.36M
        nNum--;
244
1.36M
        SdrObjUserData * pData=GetUserData(nNum);
245
1.36M
        if (pData->GetInventor() == SdrInventor::Default
246
0
            && pData->GetId() == SDRUSERDATA_OBJTEXTLINK)
247
0
        {
248
0
            return static_cast<ImpSdrObjTextLinkUserData *>(pData);
249
0
        }
250
1.36M
    }
251
2.11M
    return nullptr;
252
2.11M
}
253
254
void SdrTextObj::ImpRegisterLink()
255
0
{
256
0
    ImpSdrObjTextLinkUserData* pData=GetLinkUserData();
257
0
    sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
258
0
    if (pLinkManager!=nullptr && pData!=nullptr && pData->mpLink==nullptr) { // don't register twice
259
0
        pData->mpLink = new ImpSdrObjTextLink(this);
260
0
        pLinkManager->InsertFileLink(*pData->mpLink,sfx2::SvBaseLinkObjectType::ClientFile,pData->maFileName,
261
0
                                     !pData->maFilterName.isEmpty() ?
262
0
                                      &pData->maFilterName : nullptr);
263
0
    }
264
0
}
265
266
void SdrTextObj::ImpDeregisterLink()
267
1.79M
{
268
1.79M
    ImpSdrObjTextLinkUserData* pData=GetLinkUserData();
269
1.79M
    if (!pData)
270
1.79M
        return;
271
0
    sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
272
0
    if (pLinkManager!=nullptr && pData->mpLink!=nullptr) { // don't register twice
273
        // when doing Remove, *pLink is deleted implicitly
274
0
        pLinkManager->Remove( pData->mpLink.get() );
275
0
        pData->mpLink=nullptr;
276
0
    }
277
0
}
278
279
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */