Branch libreoffice-5-0-4
[LibreOffice.git] / sfx2 / source / appl / impldde.cxx
blob4eb4e65cd373f6b5828ab0d875ab8c96fef989d9
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(WNT)
22 #include <prewin.h>
23 #include <postwin.h>
24 #endif
26 #include "impldde.hxx"
28 #include <comphelper/string.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/fixed.hxx>
31 #include <vcl/edit.hxx>
32 #include <vcl/button.hxx>
33 #include <vcl/msgbox.hxx>
34 #include <sot/exchange.hxx>
35 #include <rtl/strbuf.hxx>
36 #include <rtl/ustring.hxx>
38 #include <sfx2/lnkbase.hxx>
39 #include <sfx2/linkmgr.hxx>
40 #include <sfx2/sfxresid.hxx>
42 #include <com/sun/star/uno/Any.hxx>
43 #include <com/sun/star/uno/Sequence.hxx>
45 #include <svl/svdde.hxx>
46 #include <sot/formats.hxx>
48 #include <unotools/securityoptions.hxx>
50 #define DDELINK_ERROR_APP 1
51 #define DDELINK_ERROR_DATA 2
53 using namespace ::com::sun::star::uno;
55 namespace sfx2
58 class SvDDELinkEditDialog : public ModalDialog
60 VclPtr<Edit> m_pEdDdeApp;
61 VclPtr<Edit> m_pEdDdeTopic;
62 VclPtr<Edit> m_pEdDdeItem;
63 VclPtr<OKButton> m_pOKButton;
65 DECL_LINK( EditHdl_Impl, Edit* );
66 public:
67 SvDDELinkEditDialog( vcl::Window* pParent, SvBaseLink* );
68 virtual ~SvDDELinkEditDialog();
69 virtual void dispose() SAL_OVERRIDE;
70 OUString GetCmd() const;
73 SvDDELinkEditDialog::SvDDELinkEditDialog( vcl::Window* pParent, SvBaseLink* pLink )
74 : ModalDialog( pParent, "LinkEditDialog", "sfx/ui/linkeditdialog.ui" )
76 get(m_pOKButton, "ok");
77 get(m_pEdDdeApp, "app");
78 get(m_pEdDdeTopic, "file");
79 get(m_pEdDdeItem, "category");
81 OUString sServer, sTopic, sItem;
82 sfx2::LinkManager::GetDisplayNames( pLink, &sServer, &sTopic, &sItem );
84 m_pEdDdeApp->SetText( sServer );
85 m_pEdDdeTopic->SetText( sTopic );
86 m_pEdDdeItem->SetText( sItem );
88 m_pEdDdeApp->SetModifyHdl( LINK( this, SvDDELinkEditDialog, EditHdl_Impl));
89 m_pEdDdeTopic->SetModifyHdl( LINK( this, SvDDELinkEditDialog, EditHdl_Impl));
90 m_pEdDdeItem->SetModifyHdl( LINK( this, SvDDELinkEditDialog, EditHdl_Impl));
92 m_pOKButton->Enable( !sServer.isEmpty() && !sTopic.isEmpty() && !sItem.isEmpty() );
95 SvDDELinkEditDialog::~SvDDELinkEditDialog()
97 disposeOnce();
100 void SvDDELinkEditDialog::dispose()
102 m_pEdDdeApp.clear();
103 m_pEdDdeTopic.clear();
104 m_pEdDdeItem.clear();
105 m_pOKButton.clear();
106 ModalDialog::dispose();
109 OUString SvDDELinkEditDialog::GetCmd() const
111 OUString sCmd( m_pEdDdeApp->GetText() ), sRet;
112 ::sfx2::MakeLnkName( sRet, &sCmd, m_pEdDdeTopic->GetText(), m_pEdDdeItem->GetText() );
113 return sRet;
116 IMPL_LINK( SvDDELinkEditDialog, EditHdl_Impl, Edit *, )
118 m_pOKButton->Enable( !m_pEdDdeApp->GetText().isEmpty() &&
119 !m_pEdDdeTopic->GetText().isEmpty() &&
120 !m_pEdDdeItem->GetText().isEmpty() );
121 return 0;
124 SvDDEObject::SvDDEObject()
125 : pConnection( 0 ), pLink( 0 ), pRequest( 0 ), pGetData( 0 ), nError( 0 )
127 SetUpdateTimeout( 100 );
128 bWaitForData = sal_False;
131 SvDDEObject::~SvDDEObject()
133 delete pLink;
134 delete pRequest;
135 delete pConnection;
138 bool SvDDEObject::GetData( ::com::sun::star::uno::Any & rData /*out param*/,
139 const OUString & rMimeType,
140 bool bSynchron )
142 if( !pConnection )
143 return false;
145 if( pConnection->GetError() ) // then we try once more
147 OUString sServer( pConnection->GetServiceName() );
148 OUString sTopic( pConnection->GetTopicName() );
150 delete pConnection;
151 pConnection = new DdeConnection( sServer, sTopic );
152 if( pConnection->GetError() )
153 nError = DDELINK_ERROR_APP;
156 if( bWaitForData ) // we are in an rekursive loop, get out again
157 return false;
159 // Lock against Reentrance
160 bWaitForData = sal_True;
162 // if you want to print, we'll wait until the data is available
163 if( bSynchron )
165 DdeRequest aReq( *pConnection, sItem, 5000 );
166 aReq.SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
167 aReq.SetFormat( SotExchange::GetFormatIdFromMimeType( rMimeType ));
169 pGetData = &rData;
171 do {
172 aReq.Execute();
173 } while( aReq.GetError() && ImplHasOtherFormat( aReq ) );
175 if( pConnection->GetError() )
176 nError = DDELINK_ERROR_DATA;
178 bWaitForData = sal_False;
180 else
182 // otherwise it will be executed asynchronously
184 if( pRequest )
185 delete pRequest;
187 pRequest = new DdeRequest( *pConnection, sItem );
188 pRequest->SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
189 pRequest->SetDoneHdl( LINK( this, SvDDEObject, ImplDoneDDEData ) );
190 pRequest->SetFormat( SotExchange::GetFormatIdFromMimeType(
191 rMimeType ) );
192 pRequest->Execute();
195 OUString aEmptyStr;
196 rData <<= aEmptyStr;
198 return 0 == pConnection->GetError();
202 bool SvDDEObject::Connect( SvBaseLink * pSvLink )
204 SfxLinkUpdateMode nLinkType = pSvLink->GetUpdateMode();
205 if( pConnection ) // Connection is already made
207 // well, then just add it as dependent
208 AddDataAdvise( pSvLink,
209 SotExchange::GetFormatMimeType( pSvLink->GetContentType()),
210 SfxLinkUpdateMode::ONCALL == nLinkType
211 ? ADVISEMODE_ONLYONCE
212 : 0 );
213 AddConnectAdvise( pSvLink );
215 return true;
218 if( !pSvLink->GetLinkManager() )
219 return false;
221 OUString sServer, sTopic;
222 sfx2::LinkManager::GetDisplayNames( pSvLink, &sServer, &sTopic, &sItem );
224 if( sServer.isEmpty() || sTopic.isEmpty() || sItem.isEmpty() )
225 return false;
227 pConnection = new DdeConnection( sServer, sTopic );
228 if( pConnection->GetError() )
230 // check if the DDE server knows the "SYSTEM" topic
231 bool bSysTopic = false;
232 if (!sTopic.equalsIgnoreAsciiCase("SYSTEM"))
234 DdeConnection aTmp(sServer, OUString("SYSTEM"));
235 bSysTopic = !aTmp.GetError();
238 if( bSysTopic )
240 // if the system topic works then the server is up but just doesn't know the original topic
241 nError = DDELINK_ERROR_DATA;
242 return false;
245 nError = DDELINK_ERROR_APP;
248 if( SfxLinkUpdateMode::ALWAYS == nLinkType && !pLink && !pConnection->GetError() )
250 // Setting up Hot Link, Data will be available at some point later on
251 pLink = new DdeHotLink( *pConnection, sItem );
252 pLink->SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
253 pLink->SetDoneHdl( LINK( this, SvDDEObject, ImplDoneDDEData ) );
254 pLink->SetFormat( pSvLink->GetContentType() );
255 pLink->Execute();
258 if( pConnection->GetError() )
259 return false;
261 AddDataAdvise( pSvLink,
262 SotExchange::GetFormatMimeType( pSvLink->GetContentType()),
263 SfxLinkUpdateMode::ONCALL == nLinkType
264 ? ADVISEMODE_ONLYONCE
265 : 0 );
266 AddConnectAdvise( pSvLink );
267 SetUpdateTimeout( 0 );
268 return true;
271 void SvDDEObject::Edit( vcl::Window* pParent, sfx2::SvBaseLink* pBaseLink, const Link<>& rEndEditHdl )
273 ScopedVclPtrInstance< SvDDELinkEditDialog > aDlg(pParent, pBaseLink);
274 if ( RET_OK == aDlg->Execute() && rEndEditHdl.IsSet() )
276 OUString sCommand = aDlg->GetCmd();
277 rEndEditHdl.Call( &sCommand );
281 bool SvDDEObject::ImplHasOtherFormat( DdeTransaction& rReq )
283 SotClipboardFormatId nFmt = SotClipboardFormatId::NONE;
284 switch( rReq.GetFormat() )
286 case SotClipboardFormatId::RTF:
287 nFmt = SotClipboardFormatId::STRING;
288 break;
290 case SotClipboardFormatId::HTML_SIMPLE:
291 case SotClipboardFormatId::HTML:
292 nFmt = SotClipboardFormatId::RTF;
293 break;
295 case SotClipboardFormatId::GDIMETAFILE:
296 nFmt = SotClipboardFormatId::BITMAP;
297 break;
299 case SotClipboardFormatId::SVXB:
300 nFmt = SotClipboardFormatId::GDIMETAFILE;
301 break;
303 // something else?
304 default: break;
306 if( nFmt != SotClipboardFormatId::NONE )
307 rReq.SetFormat( nFmt ); // try it once more
308 return SotClipboardFormatId::NONE != nFmt;
311 bool SvDDEObject::IsPending() const
312 /* [Description]
314 The method determines whether the data-object can be read from a DDE.
316 Returned is the following:
317 ERRCODE_NONE if it has been completely read
318 ERRCODE_SO_PENDING if it has not been completely read
319 ERRCODE_SO_FALSE otherwise
322 return bWaitForData;
325 bool SvDDEObject::IsDataComplete() const
327 return bWaitForData;
330 IMPL_LINK( SvDDEObject, ImplGetDDEData, DdeData*, pData )
332 SotClipboardFormatId nFmt = pData->GetFormat();
333 switch( nFmt )
335 case SotClipboardFormatId::GDIMETAFILE:
336 break;
338 case SotClipboardFormatId::BITMAP:
339 break;
341 default:
343 const sal_Char* p = static_cast<sal_Char const *>(pData->operator const void*());
344 long nLen = SotClipboardFormatId::STRING == nFmt ? (p ? strlen( p ) : 0) : (long)*pData;
346 Sequence< sal_Int8 > aSeq( reinterpret_cast<const sal_Int8*>(p), nLen );
347 if( pGetData )
349 *pGetData <<= aSeq; // Copy Data
350 pGetData = 0; // reset the pointer here
352 else
354 Any aVal;
355 aVal <<= aSeq;
356 DataChanged( SotExchange::GetFormatMimeType(
357 pData->GetFormat() ), aVal );
358 bWaitForData = sal_False;
363 return 0;
366 IMPL_LINK( SvDDEObject, ImplDoneDDEData, void*, pData )
368 bool bValid = (bool)reinterpret_cast<sal_uIntPtr>(pData);
369 if( !bValid && ( pRequest || pLink ))
371 DdeTransaction* pReq = 0;
372 if( !pLink || ( pLink && pLink->IsBusy() ))
373 pReq = pRequest; // only the one that is ready
374 else if( pRequest && pRequest->IsBusy() )
375 pReq = pLink; // only the one that is ready
377 if( pReq )
379 if( ImplHasOtherFormat( *pReq ) )
381 pReq->Execute();
383 else if( pReq == pRequest )
385 bWaitForData = sal_False;
389 else
390 // End waiting
391 bWaitForData = sal_False;
393 return 0;
398 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */