Coverage Report

Created: 2026-04-09 11:41

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