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 <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
;
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);
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() );
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()
101 SetUpdateTimeout( 100 );
102 bWaitForData
= false;
105 SvDDEObject::~SvDDEObject()
112 bool SvDDEObject::GetData( css::uno::Any
& rData
/*out param*/,
113 const OUString
& rMimeType
,
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
130 // Lock against Reentrance
133 // if you want to print, we'll wait until the data is available
136 DdeRequest
aReq( *pConnection
, sItem
, 5000 );
137 aReq
.SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
138 aReq
.SetFormat( SotExchange::GetFormatIdFromMimeType( rMimeType
));
144 } while( aReq
.GetError() && ImplHasOtherFormat( aReq
) );
146 bWaitForData
= false;
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(
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
177 AddConnectAdvise( pSvLink
);
182 if( !pSvLink
->GetLinkManager() )
185 OUString sServer
, sTopic
;
186 sfx2::LinkManager::GetDisplayNames( pSvLink
, &sServer
, &sTopic
, &sItem
);
188 if( sServer
.isEmpty() || sTopic
.isEmpty() || sItem
.isEmpty() )
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();
204 // if the system topic works then the server is up but just doesn't know the original topic
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() );
219 if( pConnection
->GetError() )
222 AddDataAdvise( pSvLink
,
223 SotExchange::GetFormatMimeType( pSvLink
->GetContentType()),
224 SfxLinkUpdateMode::ONCALL
== nLinkType
225 ? ADVISEMODE_ONLYONCE
227 AddConnectAdvise( pSvLink
);
228 SetUpdateTimeout( 0 );
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
;
251 case SotClipboardFormatId::HTML_SIMPLE
:
252 case SotClipboardFormatId::HTML
:
253 nFmt
= SotClipboardFormatId::RTF
;
256 case SotClipboardFormatId::GDIMETAFILE
:
257 nFmt
= SotClipboardFormatId::BITMAP
;
260 case SotClipboardFormatId::SVXB
:
261 nFmt
= SotClipboardFormatId::GDIMETAFILE
;
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.
280 bool SvDDEObject::IsDataComplete() const
285 IMPL_LINK( SvDDEObject
, ImplGetDDEData
, const DdeData
*, pData
, void )
287 SotClipboardFormatId nFmt
= pData
->GetFormat();
290 case SotClipboardFormatId::GDIMETAFILE
:
293 case SotClipboardFormatId::BITMAP
:
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
);
304 *pGetData
<<= aSeq
; // Copy Data
305 pGetData
= nullptr; // reset the pointer here
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
331 if( ImplHasOtherFormat( *pReq
) )
335 else if( pReq
== pRequest
.get() )
337 bWaitForData
= false;
343 bWaitForData
= false;
348 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */