LibreOffice Module sfx2 (master) 1
impldde.cxx
Go to the documentation of this file.
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
21#if defined(_WIN32)
22#include <prewin.h>
23#include <postwin.h>
24#endif
25
26#include "impldde.hxx"
27
28#include <vcl/weld.hxx>
29#include <sot/exchange.hxx>
30#include <rtl/ustring.hxx>
31
32#include <sfx2/lnkbase.hxx>
33#include <sfx2/linkmgr.hxx>
34
35#include <com/sun/star/uno/Any.hxx>
36#include <com/sun/star/uno/Sequence.hxx>
37
38#include <svl/svdde.hxx>
39#include <sot/formats.hxx>
40
41using namespace ::com::sun::star::uno;
42
43namespace sfx2
44{
45
46namespace {
47
48class SvDDELinkEditDialog : public weld::GenericDialogController
49{
50 std::unique_ptr<weld::Entry> m_xEdDdeApp;
51 std::unique_ptr<weld::Entry> m_xEdDdeTopic;
52 std::unique_ptr<weld::Entry> m_xEdDdeItem;
53 std::unique_ptr<weld::Button> m_xOKButton;
54
55 DECL_LINK(EditHdl_Impl, weld::Entry&, void);
56public:
57 SvDDELinkEditDialog(weld::Window* pParent, SvBaseLink const*);
58 OUString GetCmd() const;
59};
60
61}
62
63SvDDELinkEditDialog::SvDDELinkEditDialog(weld::Window* pParent, SvBaseLink const * pLink)
64 : GenericDialogController(pParent, "sfx/ui/linkeditdialog.ui", "LinkEditDialog")
65 , m_xEdDdeApp(m_xBuilder->weld_entry("app"))
66 , m_xEdDdeTopic(m_xBuilder->weld_entry("file"))
67 , m_xEdDdeItem(m_xBuilder->weld_entry("category"))
68 , m_xOKButton(m_xBuilder->weld_button("ok"))
69{
70 OUString sServer, sTopic, sItem;
71 sfx2::LinkManager::GetDisplayNames( pLink, &sServer, &sTopic, &sItem );
72
73 m_xEdDdeApp->set_text( sServer );
74 m_xEdDdeTopic->set_text( sTopic );
75 m_xEdDdeItem->set_text( sItem );
76
77 m_xEdDdeApp->connect_changed( LINK( this, SvDDELinkEditDialog, EditHdl_Impl));
78 m_xEdDdeTopic->connect_changed( LINK( this, SvDDELinkEditDialog, EditHdl_Impl));
79 m_xEdDdeItem->connect_changed( LINK( this, SvDDELinkEditDialog, EditHdl_Impl));
80
81 m_xOKButton->set_sensitive(!sServer.isEmpty() && !sTopic.isEmpty() && !sItem.isEmpty());
82}
83
84OUString SvDDELinkEditDialog::GetCmd() const
85{
86 OUString sCmd( m_xEdDdeApp->get_text() ), sRet;
87 ::sfx2::MakeLnkName( sRet, &sCmd, m_xEdDdeTopic->get_text(), m_xEdDdeItem->get_text() );
88 return sRet;
89}
90
91IMPL_LINK_NOARG( SvDDELinkEditDialog, EditHdl_Impl, weld::Entry&, void)
92{
93 m_xOKButton->set_sensitive(!m_xEdDdeApp->get_text().isEmpty() &&
94 !m_xEdDdeTopic->get_text().isEmpty() &&
95 !m_xEdDdeItem->get_text().isEmpty() );
96}
97
98SvDDEObject::SvDDEObject()
99 : pGetData( nullptr )
100{
101 SetUpdateTimeout( 100 );
102 bWaitForData = false;
103}
104
106{
107 pLink.reset();
108 pRequest.reset();
109 pConnection.reset();
110}
111
112bool SvDDEObject::GetData( css::uno::Any & rData /*out param*/,
113 const OUString & rMimeType,
114 bool bSynchron )
115{
116 if( !pConnection )
117 return false;
118
119 if( pConnection->GetError() ) // then we try once more
120 {
121 OUString sServer( pConnection->GetServiceName() );
122 OUString sTopic( pConnection->GetTopicName() );
123
124 pConnection.reset( new DdeConnection( sServer, sTopic ) );
125 }
126
127 if( bWaitForData ) // we are in a recursive loop, get out again
128 return false;
129
130 // Lock against Reentrance
131 bWaitForData = true;
132
133 // if you want to print, we'll wait until the data is available
134 if( bSynchron )
135 {
136 DdeRequest aReq( *pConnection, sItem, 5000 );
137 aReq.SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
139
140 pGetData = &rData;
141
142 do {
143 aReq.Execute();
144 } while( aReq.GetError() && ImplHasOtherFormat( aReq ) );
145
146 bWaitForData = false;
147 }
148 else
149 {
150 // otherwise it will be executed asynchronously
151 {
152 pRequest.reset( new DdeRequest( *pConnection, sItem ) );
153 pRequest->SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
154 pRequest->SetDoneHdl( LINK( this, SvDDEObject, ImplDoneDDEData ) );
156 rMimeType ) );
157 pRequest->Execute();
158 }
159
160 rData <<= OUString();
161 }
162 return 0 == pConnection->GetError();
163}
164
165
167{
168 SfxLinkUpdateMode nLinkType = pSvLink->GetUpdateMode();
169 if( pConnection ) // Connection is already made
170 {
171 // well, then just add it as dependent
172 AddDataAdvise( pSvLink,
174 SfxLinkUpdateMode::ONCALL == nLinkType
176 : 0 );
177 AddConnectAdvise( pSvLink );
178
179 return true;
180 }
181
182 if( !pSvLink->GetLinkManager() )
183 return false;
184
185 OUString sServer, sTopic;
186 sfx2::LinkManager::GetDisplayNames( pSvLink, &sServer, &sTopic, &sItem );
187
188 if( sServer.isEmpty() || sTopic.isEmpty() || sItem.isEmpty() )
189 return false;
190
191 pConnection.reset( new DdeConnection( sServer, sTopic ) );
192 if( pConnection->GetError() )
193 {
194 // check if the DDE server knows the "SYSTEM" topic
195 bool bSysTopic = false;
196 if (!sTopic.equalsIgnoreAsciiCase("SYSTEM"))
197 {
198 DdeConnection aTmp(sServer, "SYSTEM");
199 bSysTopic = !aTmp.GetError();
200 }
201
202 if( bSysTopic )
203 {
204 // if the system topic works then the server is up but just doesn't know the original topic
205 return false;
206 }
207 }
208
209 if( SfxLinkUpdateMode::ALWAYS == nLinkType && !pLink && !pConnection->GetError() )
210 {
211 // Setting up Hot Link, Data will be available at some point later on
212 pLink.reset( new DdeHotLink( *pConnection, sItem ) );
213 pLink->SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
214 pLink->SetDoneHdl( LINK( this, SvDDEObject, ImplDoneDDEData ) );
215 pLink->SetFormat( pSvLink->GetContentType() );
216 pLink->Execute();
217 }
218
219 if( pConnection->GetError() )
220 return false;
221
222 AddDataAdvise( pSvLink,
224 SfxLinkUpdateMode::ONCALL == nLinkType
226 : 0 );
227 AddConnectAdvise( pSvLink );
228 SetUpdateTimeout( 0 );
229 return true;
230}
231
233{
234 SvDDELinkEditDialog aDlg(pParent, pBaseLink);
235 if (RET_OK == aDlg.run() && rEndEditHdl.IsSet())
236 {
237 OUString sCommand = aDlg.GetCmd();
238 rEndEditHdl.Call( sCommand );
239 }
240}
241
243{
244 SotClipboardFormatId nFmt = SotClipboardFormatId::NONE;
245 switch( rReq.GetFormat() )
246 {
247 case SotClipboardFormatId::RTF:
248 nFmt = SotClipboardFormatId::STRING;
249 break;
250
251 case SotClipboardFormatId::HTML_SIMPLE:
252 case SotClipboardFormatId::HTML:
253 nFmt = SotClipboardFormatId::RTF;
254 break;
255
256 case SotClipboardFormatId::GDIMETAFILE:
257 nFmt = SotClipboardFormatId::BITMAP;
258 break;
259
260 case SotClipboardFormatId::SVXB:
261 nFmt = SotClipboardFormatId::GDIMETAFILE;
262 break;
263
264 // something else?
265 default: break;
266 }
267 if( nFmt != SotClipboardFormatId::NONE )
268 rReq.SetFormat( nFmt ); // try it once more
269 return SotClipboardFormatId::NONE != nFmt;
270}
271
273/*
274 The method determines whether the data-object can be read from a DDE.
275*/
276{
277 return bWaitForData;
278}
279
281{
282 return bWaitForData;
283}
284
285IMPL_LINK( SvDDEObject, ImplGetDDEData, const DdeData*, pData, void )
286{
287 SotClipboardFormatId nFmt = pData->GetFormat();
288 switch( nFmt )
289 {
290 case SotClipboardFormatId::GDIMETAFILE:
291 break;
292
293 case SotClipboardFormatId::BITMAP:
294 break;
295
296 default:
297 {
298 const char* p = static_cast<char const *>(pData->getData());
299 tools::Long nLen = SotClipboardFormatId::STRING == nFmt ? (p ? strlen( p ) : 0) : pData->getSize();
300
301 Sequence< sal_Int8 > aSeq( reinterpret_cast<const sal_Int8*>(p), nLen );
302 if( pGetData )
303 {
304 *pGetData <<= aSeq; // Copy Data
305 pGetData = nullptr; // reset the pointer here
306 }
307 else
308 {
309 Any aVal;
310 aVal <<= aSeq;
312 pData->GetFormat() ), aVal );
313 bWaitForData = false;
314 }
315 }
316 }
317}
318
319IMPL_LINK( SvDDEObject, ImplDoneDDEData, bool, bValid, void )
320{
321 if( !bValid && ( pRequest || pLink ))
322 {
323 DdeTransaction* pReq = nullptr;
324 if( !pLink || ( pLink && pLink->IsBusy() ))
325 pReq = pRequest.get(); // only the one that is ready
326 else if( pRequest && pRequest->IsBusy() )
327 pReq = pLink.get(); // only the one that is ready
328
329 if( pReq )
330 {
331 if( ImplHasOtherFormat( *pReq ) )
332 {
333 pReq->Execute();
334 }
335 else if( pReq == pRequest.get() )
336 {
337 bWaitForData = false;
338 }
339 }
340 }
341 else
342 // End waiting
343 bWaitForData = false;
344}
345
346}
347
348/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
tools::Long GetError() const
tools::Long GetError() const
void SetFormat(SotClipboardFormatId nFmt)
void SetDataHdl(const Link< const DdeData *, void > &rLink)
SotClipboardFormatId GetFormat() const
static OUString GetFormatMimeType(SotClipboardFormatId nFormat)
static SotClipboardFormatId GetFormatIdFromMimeType(std::u16string_view rMimeType)
static bool GetDisplayNames(const SvBaseLink *, OUString *pType, OUString *pFile=nullptr, OUString *pLink=nullptr, OUString *pFilter=nullptr)
Definition: linkmgr2.cxx:218
virtual bool Connect(SvBaseLink *) override
Definition: impldde.cxx:166
virtual ~SvDDEObject() override
Definition: impldde.cxx:105
std::unique_ptr< DdeRequest > pRequest
Definition: impldde.hxx:41
std::unique_ptr< DdeLink > pLink
Definition: impldde.hxx:40
virtual bool IsDataComplete() const override
Definition: impldde.cxx:280
static bool ImplHasOtherFormat(DdeTransaction &)
Definition: impldde.cxx:242
std::unique_ptr< DdeConnection > pConnection
Definition: impldde.hxx:39
virtual bool GetData(css::uno::Any &rData, const OUString &aMimeType, bool bSynchron=false) override
Definition: impldde.cxx:112
virtual void Edit(weld::Window *pParent, sfx2::SvBaseLink *pBaseLink, const Link< const OUString &, void > &rEndEditHdl) override
Definition: impldde.cxx:232
OUString sItem
Definition: impldde.hxx:37
virtual bool IsPending() const override
Definition: impldde.cxx:272
css::uno::Any * pGetData
Definition: impldde.hxx:42
void AddDataAdvise(SvBaseLink *, const OUString &rMimeType, sal_uInt16 nAdviceMode)
Definition: linksrc.cxx:342
void AddConnectAdvise(SvBaseLink *)
Definition: linksrc.cxx:361
void SetUpdateTimeout(sal_uInt64 nTimeMs)
Definition: linksrc.cxx:237
DECL_LINK(CheckNameHdl, SvxNameDialog &, bool)
SotClipboardFormatId
std::unique_ptr< weld::Entry > m_xEdDdeApp
Definition: impldde.cxx:50
std::unique_ptr< weld::Entry > m_xEdDdeItem
Definition: impldde.cxx:52
std::unique_ptr< weld::Button > m_xOKButton
Definition: impldde.cxx:53
std::unique_ptr< weld::Entry > m_xEdDdeTopic
Definition: impldde.cxx:51
void * p
#define ADVISEMODE_ONLYONCE
Definition: linksrc.hxx:43
SvBaseLink * pLink
Definition: lnkbase2.cxx:81
Sequence< sal_Int8 > aSeq
Definition: lnkbase2.cxx:83
SfxLinkUpdateMode
Definition: lnkbase.hxx:38
std::unique_ptr< sal_Int32[]> pData
IMPL_LINK_NOARG(SvDDELinkEditDialog, EditHdl_Impl, weld::Entry &, void)
Definition: impldde.cxx:91
IMPL_LINK(SvDDEObject, ImplGetDDEData, const DdeData *, pData, void)
Definition: impldde.cxx:285
void MakeLnkName(OUString &rName, const OUString *pType, std::u16string_view rFile, std::u16string_view rLink, const OUString *pFilter)
Definition: linkmgr2.cxx:379
long Long
signed char sal_Int8
RET_OK