1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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
;
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
* );
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()
100 void SvDDELinkEditDialog::dispose()
103 m_pEdDdeTopic
.clear();
104 m_pEdDdeItem
.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() );
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() );
124 SvDDEObject::SvDDEObject()
125 : pConnection( 0 ), pLink( 0 ), pRequest( 0 ), pGetData( 0 ), nError( 0 )
127 SetUpdateTimeout( 100 );
128 bWaitForData
= sal_False
;
131 SvDDEObject::~SvDDEObject()
138 bool SvDDEObject::GetData( ::com::sun::star::uno::Any
& rData
/*out param*/,
139 const OUString
& rMimeType
,
145 if( pConnection
->GetError() ) // then we try once more
147 OUString
sServer( pConnection
->GetServiceName() );
148 OUString
sTopic( pConnection
->GetTopicName() );
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
159 // Lock against Reentrance
160 bWaitForData
= sal_True
;
162 // if you want to print, we'll wait until the data is available
165 DdeRequest
aReq( *pConnection
, sItem
, 5000 );
166 aReq
.SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
167 aReq
.SetFormat( SotExchange::GetFormatIdFromMimeType( rMimeType
));
173 } while( aReq
.GetError() && ImplHasOtherFormat( aReq
) );
175 if( pConnection
->GetError() )
176 nError
= DDELINK_ERROR_DATA
;
178 bWaitForData
= sal_False
;
182 // otherwise it will be executed asynchronously
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(
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
213 AddConnectAdvise( pSvLink
);
218 if( !pSvLink
->GetLinkManager() )
221 OUString sServer
, sTopic
;
222 sfx2::LinkManager::GetDisplayNames( pSvLink
, &sServer
, &sTopic
, &sItem
);
224 if( sServer
.isEmpty() || sTopic
.isEmpty() || sItem
.isEmpty() )
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();
240 // if the system topic works then the server is up but just doesn't know the original topic
241 nError
= DDELINK_ERROR_DATA
;
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() );
258 if( pConnection
->GetError() )
261 AddDataAdvise( pSvLink
,
262 SotExchange::GetFormatMimeType( pSvLink
->GetContentType()),
263 SfxLinkUpdateMode::ONCALL
== nLinkType
264 ? ADVISEMODE_ONLYONCE
266 AddConnectAdvise( pSvLink
);
267 SetUpdateTimeout( 0 );
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
;
290 case SotClipboardFormatId::HTML_SIMPLE
:
291 case SotClipboardFormatId::HTML
:
292 nFmt
= SotClipboardFormatId::RTF
;
295 case SotClipboardFormatId::GDIMETAFILE
:
296 nFmt
= SotClipboardFormatId::BITMAP
;
299 case SotClipboardFormatId::SVXB
:
300 nFmt
= SotClipboardFormatId::GDIMETAFILE
;
306 if( nFmt
!= SotClipboardFormatId::NONE
)
307 rReq
.SetFormat( nFmt
); // try it once more
308 return SotClipboardFormatId::NONE
!= nFmt
;
311 bool SvDDEObject::IsPending() const
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
325 bool SvDDEObject::IsDataComplete() const
330 IMPL_LINK( SvDDEObject
, ImplGetDDEData
, DdeData
*, pData
)
332 SotClipboardFormatId nFmt
= pData
->GetFormat();
335 case SotClipboardFormatId::GDIMETAFILE
:
338 case SotClipboardFormatId::BITMAP
:
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
);
349 *pGetData
<<= aSeq
; // Copy Data
350 pGetData
= 0; // reset the pointer here
356 DataChanged( SotExchange::GetFormatMimeType(
357 pData
->GetFormat() ), aVal
);
358 bWaitForData
= sal_False
;
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
379 if( ImplHasOtherFormat( *pReq
) )
383 else if( pReq
== pRequest
)
385 bWaitForData
= sal_False
;
391 bWaitForData
= sal_False
;
398 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */