Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / appl / impldde.cxx
blobc70cb4cb6a19af9cfc54723aeecffbe8afb6daa8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #if defined(_WIN32)
22 #include <prewin.h>
23 #include <postwin.h>
24 #endif
26 #include "impldde.hxx"
28 #include <vcl/weld.hxx>
29 #include <sot/exchange.hxx>
30 #include <rtl/ustring.hxx>
32 #include <sfx2/lnkbase.hxx>
33 #include <sfx2/linkmgr.hxx>
35 #include <com/sun/star/uno/Any.hxx>
36 #include <com/sun/star/uno/Sequence.hxx>
38 #include <svl/svdde.hxx>
39 #include <sot/formats.hxx>
41 using namespace ::com::sun::star::uno;
43 namespace sfx2
46 namespace {
48 class SvDDELinkEditDialog : public weld::GenericDialogController
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;
55 DECL_LINK(EditHdl_Impl, weld::Entry&, void);
56 public:
57 SvDDELinkEditDialog(weld::Window* pParent, SvBaseLink const*);
58 OUString GetCmd() const;
63 SvDDELinkEditDialog::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"))
70 OUString sServer, sTopic, sItem;
71 sfx2::LinkManager::GetDisplayNames( pLink, &sServer, &sTopic, &sItem );
73 m_xEdDdeApp->set_text( sServer );
74 m_xEdDdeTopic->set_text( sTopic );
75 m_xEdDdeItem->set_text( sItem );
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));
81 m_xOKButton->set_sensitive(!sServer.isEmpty() && !sTopic.isEmpty() && !sItem.isEmpty());
84 OUString SvDDELinkEditDialog::GetCmd() const
86 OUString sCmd( m_xEdDdeApp->get_text() ), sRet;
87 ::sfx2::MakeLnkName( sRet, &sCmd, m_xEdDdeTopic->get_text(), m_xEdDdeItem->get_text() );
88 return sRet;
91 IMPL_LINK_NOARG( SvDDELinkEditDialog, EditHdl_Impl, weld::Entry&, void)
93 m_xOKButton->set_sensitive(!m_xEdDdeApp->get_text().isEmpty() &&
94 !m_xEdDdeTopic->get_text().isEmpty() &&
95 !m_xEdDdeItem->get_text().isEmpty() );
98 SvDDEObject::SvDDEObject()
99 : pGetData( nullptr )
101 SetUpdateTimeout( 100 );
102 bWaitForData = false;
105 SvDDEObject::~SvDDEObject()
107 pLink.reset();
108 pRequest.reset();
109 pConnection.reset();
112 bool SvDDEObject::GetData( css::uno::Any & rData /*out param*/,
113 const OUString & rMimeType,
114 bool bSynchron )
116 if( !pConnection )
117 return false;
119 if( pConnection->GetError() ) // then we try once more
121 OUString sServer( pConnection->GetServiceName() );
122 OUString sTopic( pConnection->GetTopicName() );
124 pConnection.reset( new DdeConnection( sServer, sTopic ) );
127 if( bWaitForData ) // we are in a recursive loop, get out again
128 return false;
130 // Lock against Reentrance
131 bWaitForData = true;
133 // if you want to print, we'll wait until the data is available
134 if( bSynchron )
136 DdeRequest aReq( *pConnection, sItem, 5000 );
137 aReq.SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
138 aReq.SetFormat( SotExchange::GetFormatIdFromMimeType( rMimeType ));
140 pGetData = &rData;
142 do {
143 aReq.Execute();
144 } while( aReq.GetError() && ImplHasOtherFormat( aReq ) );
146 bWaitForData = false;
148 else
150 // otherwise it will be executed asynchronously
152 pRequest.reset( new DdeRequest( *pConnection, sItem ) );
153 pRequest->SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
154 pRequest->SetDoneHdl( LINK( this, SvDDEObject, ImplDoneDDEData ) );
155 pRequest->SetFormat( SotExchange::GetFormatIdFromMimeType(
156 rMimeType ) );
157 pRequest->Execute();
160 rData <<= OUString();
162 return 0 == pConnection->GetError();
166 bool SvDDEObject::Connect( SvBaseLink * pSvLink )
168 SfxLinkUpdateMode nLinkType = pSvLink->GetUpdateMode();
169 if( pConnection ) // Connection is already made
171 // well, then just add it as dependent
172 AddDataAdvise( pSvLink,
173 SotExchange::GetFormatMimeType( pSvLink->GetContentType()),
174 SfxLinkUpdateMode::ONCALL == nLinkType
175 ? ADVISEMODE_ONLYONCE
176 : 0 );
177 AddConnectAdvise( pSvLink );
179 return true;
182 if( !pSvLink->GetLinkManager() )
183 return false;
185 OUString sServer, sTopic;
186 sfx2::LinkManager::GetDisplayNames( pSvLink, &sServer, &sTopic, &sItem );
188 if( sServer.isEmpty() || sTopic.isEmpty() || sItem.isEmpty() )
189 return false;
191 pConnection.reset( new DdeConnection( sServer, sTopic ) );
192 if( pConnection->GetError() )
194 // check if the DDE server knows the "SYSTEM" topic
195 bool bSysTopic = false;
196 if (!sTopic.equalsIgnoreAsciiCase("SYSTEM"))
198 DdeConnection aTmp(sServer, "SYSTEM");
199 bSysTopic = !aTmp.GetError();
202 if( bSysTopic )
204 // if the system topic works then the server is up but just doesn't know the original topic
205 return false;
209 if( SfxLinkUpdateMode::ALWAYS == nLinkType && !pLink && !pConnection->GetError() )
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();
219 if( pConnection->GetError() )
220 return false;
222 AddDataAdvise( pSvLink,
223 SotExchange::GetFormatMimeType( pSvLink->GetContentType()),
224 SfxLinkUpdateMode::ONCALL == nLinkType
225 ? ADVISEMODE_ONLYONCE
226 : 0 );
227 AddConnectAdvise( pSvLink );
228 SetUpdateTimeout( 0 );
229 return true;
232 void SvDDEObject::Edit(weld::Window* pParent, sfx2::SvBaseLink* pBaseLink, const Link<const OUString&, void>& rEndEditHdl)
234 SvDDELinkEditDialog aDlg(pParent, pBaseLink);
235 if (RET_OK == aDlg.run() && rEndEditHdl.IsSet())
237 OUString sCommand = aDlg.GetCmd();
238 rEndEditHdl.Call( sCommand );
242 bool SvDDEObject::ImplHasOtherFormat( DdeTransaction& rReq )
244 SotClipboardFormatId nFmt = SotClipboardFormatId::NONE;
245 switch( rReq.GetFormat() )
247 case SotClipboardFormatId::RTF:
248 nFmt = SotClipboardFormatId::STRING;
249 break;
251 case SotClipboardFormatId::HTML_SIMPLE:
252 case SotClipboardFormatId::HTML:
253 nFmt = SotClipboardFormatId::RTF;
254 break;
256 case SotClipboardFormatId::GDIMETAFILE:
257 nFmt = SotClipboardFormatId::BITMAP;
258 break;
260 case SotClipboardFormatId::SVXB:
261 nFmt = SotClipboardFormatId::GDIMETAFILE;
262 break;
264 // something else?
265 default: break;
267 if( nFmt != SotClipboardFormatId::NONE )
268 rReq.SetFormat( nFmt ); // try it once more
269 return SotClipboardFormatId::NONE != nFmt;
272 bool SvDDEObject::IsPending() const
274 The method determines whether the data-object can be read from a DDE.
277 return bWaitForData;
280 bool SvDDEObject::IsDataComplete() const
282 return bWaitForData;
285 IMPL_LINK( SvDDEObject, ImplGetDDEData, const DdeData*, pData, void )
287 SotClipboardFormatId nFmt = pData->GetFormat();
288 switch( nFmt )
290 case SotClipboardFormatId::GDIMETAFILE:
291 break;
293 case SotClipboardFormatId::BITMAP:
294 break;
296 default:
298 const char* p = static_cast<char const *>(pData->getData());
299 tools::Long nLen = SotClipboardFormatId::STRING == nFmt ? (p ? strlen( p ) : 0) : pData->getSize();
301 Sequence< sal_Int8 > aSeq( reinterpret_cast<const sal_Int8*>(p), nLen );
302 if( pGetData )
304 *pGetData <<= aSeq; // Copy Data
305 pGetData = nullptr; // reset the pointer here
307 else
309 Any aVal;
310 aVal <<= aSeq;
311 DataChanged( SotExchange::GetFormatMimeType(
312 pData->GetFormat() ), aVal );
313 bWaitForData = false;
319 IMPL_LINK( SvDDEObject, ImplDoneDDEData, bool, bValid, void )
321 if( !bValid && ( pRequest || pLink ))
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
329 if( pReq )
331 if( ImplHasOtherFormat( *pReq ) )
333 pReq->Execute();
335 else if( pReq == pRequest.get() )
337 bWaitForData = false;
341 else
342 // End waiting
343 bWaitForData = false;
348 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */