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/svapp.hxx>
29 #include <vcl/fixed.hxx>
30 #include <vcl/edit.hxx>
31 #include <vcl/button.hxx>
32 #include <vcl/msgbox.hxx>
33 #include <sot/exchange.hxx>
34 #include <rtl/strbuf.hxx>
35 #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 #define DDELINK_ERROR_APP 1
49 #define DDELINK_ERROR_DATA 2
51 using namespace ::com::sun::star::uno
;
56 class SvDDELinkEditDialog
: public ModalDialog
60 FixedText aFtDdeTopic
;
64 FixedLine aGroupDdeChg
;
66 CancelButton aCancelButton1
;
68 DECL_STATIC_LINK( SvDDELinkEditDialog
, EditHdl_Impl
, Edit
* );
70 SvDDELinkEditDialog( Window
* pParent
, SvBaseLink
* );
71 OUString
GetCmd() const;
74 SvDDELinkEditDialog::SvDDELinkEditDialog( Window
* pParent
, SvBaseLink
* pLink
)
75 : ModalDialog( pParent
, SfxResId( MD_DDE_LINKEDIT
) ),
76 aFtDdeApp( this, SfxResId( FT_DDE_APP
) ),
77 aEdDdeApp( this, SfxResId( ED_DDE_APP
) ),
78 aFtDdeTopic( this, SfxResId( FT_DDE_TOPIC
) ),
79 aEdDdeTopic( this, SfxResId( ED_DDE_TOPIC
) ),
80 aFtDdeItem( this, SfxResId( FT_DDE_ITEM
) ),
81 aEdDdeItem( this, SfxResId( ED_DDE_ITEM
) ),
82 aGroupDdeChg( this, SfxResId( GROUP_DDE_CHG
) ),
83 aOKButton1( this, SfxResId( 1 ) ),
84 aCancelButton1( this, SfxResId( 1 ) )
88 OUString sServer
, sTopic
, sItem
;
89 pLink
->GetLinkManager()->GetDisplayNames( pLink
, &sServer
, &sTopic
, &sItem
);
91 aEdDdeApp
.SetText( sServer
);
92 aEdDdeTopic
.SetText( sTopic
);
93 aEdDdeItem
.SetText( sItem
);
95 aEdDdeApp
.SetModifyHdl( STATIC_LINK( this, SvDDELinkEditDialog
, EditHdl_Impl
));
96 aEdDdeTopic
.SetModifyHdl( STATIC_LINK( this, SvDDELinkEditDialog
, EditHdl_Impl
));
97 aEdDdeItem
.SetModifyHdl( STATIC_LINK( this, SvDDELinkEditDialog
, EditHdl_Impl
));
99 aOKButton1
.Enable( !sServer
.isEmpty() && !sTopic
.isEmpty() && !sItem
.isEmpty() );
102 OUString
SvDDELinkEditDialog::GetCmd() const
104 OUString
sCmd( aEdDdeApp
.GetText() ), sRet
;
105 ::sfx2::MakeLnkName( sRet
, &sCmd
, aEdDdeTopic
.GetText(), aEdDdeItem
.GetText() );
109 IMPL_STATIC_LINK( SvDDELinkEditDialog
, EditHdl_Impl
, Edit
*, pEdit
)
111 (void)pEdit
; // unused variable
112 pThis
->aOKButton1
.Enable( !pThis
->aEdDdeApp
.GetText().isEmpty() &&
113 !pThis
->aEdDdeTopic
.GetText().isEmpty() &&
114 !pThis
->aEdDdeItem
.GetText().isEmpty() );
118 SvDDEObject::SvDDEObject()
119 : pConnection( 0 ), pLink( 0 ), pRequest( 0 ), pGetData( 0 ), nError( 0 )
121 SetUpdateTimeout( 100 );
122 bWaitForData
= sal_False
;
125 SvDDEObject::~SvDDEObject()
132 sal_Bool
SvDDEObject::GetData( ::com::sun::star::uno::Any
& rData
/*out param*/,
133 const OUString
& rMimeType
,
139 if( pConnection
->GetError() ) // then we try once more
141 OUString
sServer( pConnection
->GetServiceName() );
142 OUString
sTopic( pConnection
->GetTopicName() );
145 pConnection
= new DdeConnection( sServer
, sTopic
);
146 if( pConnection
->GetError() )
147 nError
= DDELINK_ERROR_APP
;
150 if( bWaitForData
) // we are in an rekursive loop, get out again
153 // Lock against Reentrance
154 bWaitForData
= sal_True
;
156 // if you want to print, we'll wait until the data is available
159 DdeRequest
aReq( *pConnection
, sItem
, 5000 );
160 aReq
.SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
161 aReq
.SetFormat( SotExchange::GetFormatIdFromMimeType( rMimeType
));
167 } while( aReq
.GetError() && ImplHasOtherFormat( aReq
) );
169 if( pConnection
->GetError() )
170 nError
= DDELINK_ERROR_DATA
;
172 bWaitForData
= sal_False
;
176 // otherwise it will be executed asynchronously
181 pRequest
= new DdeRequest( *pConnection
, sItem
);
182 pRequest
->SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
183 pRequest
->SetDoneHdl( LINK( this, SvDDEObject
, ImplDoneDDEData
) );
184 pRequest
->SetFormat( SotExchange::GetFormatIdFromMimeType(
192 return 0 == pConnection
->GetError();
196 sal_Bool
SvDDEObject::Connect( SvBaseLink
* pSvLink
)
199 static sal_Bool bInWinExec
= sal_False
;
201 sal_uInt16 nLinkType
= pSvLink
->GetUpdateMode();
202 if( pConnection
) // Connection is already made
204 // well, then just add it as dependent
205 AddDataAdvise( pSvLink
,
206 SotExchange::GetFormatMimeType( pSvLink
->GetContentType()),
207 LINKUPDATE_ONCALL
== nLinkType
208 ? ADVISEMODE_ONLYONCE
210 AddConnectAdvise( pSvLink
);
215 if( !pSvLink
->GetLinkManager() )
218 OUString sServer
, sTopic
;
219 pSvLink
->GetLinkManager()->GetDisplayNames( pSvLink
, &sServer
, &sTopic
, &sItem
);
221 if( sServer
.isEmpty() || sTopic
.isEmpty() || sItem
.isEmpty() )
224 pConnection
= new DdeConnection( sServer
, sTopic
);
225 if( pConnection
->GetError() )
227 // Is it possible to address the system-Topic?
228 // then the server is up, it just does not know the topic!
229 if( sTopic
.equalsIgnoreAsciiCase( "SYSTEM" ) )
233 DdeConnection
aTmp(sServer
, OUString("SYSTEM"));
234 bSysTopic
= !aTmp
.GetError();
239 nError
= DDELINK_ERROR_DATA
;
242 // otherwise in Win/WinNT, start the Application directly
247 // Server not up, try once more to start it.
250 OStringBuffer
aCmdLine(OUStringToOString(sServer
, RTL_TEXTENCODING_ASCII_US
));
251 aCmdLine
.append(".exe ");
252 aCmdLine
.append(OUStringToOString(sTopic
, RTL_TEXTENCODING_ASCII_US
));
254 if( WinExec( aCmdLine
.getStr(), SW_SHOWMINIMIZED
) < 32 )
255 nError
= DDELINK_ERROR_APP
;
261 bInWinExec
= sal_True
;
262 Application::Reschedule();
263 bInWinExec
= sal_False
;
266 pConnection
= new DdeConnection( sServer
, sTopic
);
267 if( !pConnection
->GetError() )
273 nError
= DDELINK_ERROR_APP
;
280 nError
= DDELINK_ERROR_APP
;
284 if( LINKUPDATE_ALWAYS
== nLinkType
&& !pLink
&& !pConnection
->GetError() )
286 // Setting up Hot Link, Data will be available at some point later on
287 pLink
= new DdeHotLink( *pConnection
, sItem
);
288 pLink
->SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
289 pLink
->SetDoneHdl( LINK( this, SvDDEObject
, ImplDoneDDEData
) );
290 pLink
->SetFormat( pSvLink
->GetContentType() );
294 if( pConnection
->GetError() )
297 AddDataAdvise( pSvLink
,
298 SotExchange::GetFormatMimeType( pSvLink
->GetContentType()),
299 LINKUPDATE_ONCALL
== nLinkType
300 ? ADVISEMODE_ONLYONCE
302 AddConnectAdvise( pSvLink
);
303 SetUpdateTimeout( 0 );
307 void SvDDEObject::Edit( Window
* pParent
, sfx2::SvBaseLink
* pBaseLink
, const Link
& rEndEditHdl
)
309 SvDDELinkEditDialog
aDlg( pParent
, pBaseLink
);
310 if ( RET_OK
== aDlg
.Execute() && rEndEditHdl
.IsSet() )
312 OUString sCommand
= aDlg
.GetCmd();
313 rEndEditHdl
.Call( &sCommand
);
317 sal_Bool
SvDDEObject::ImplHasOtherFormat( DdeTransaction
& rReq
)
320 switch( rReq
.GetFormat() )
323 nFmt
= FORMAT_STRING
;
326 case SOT_FORMATSTR_ID_HTML_SIMPLE
:
327 case SOT_FORMATSTR_ID_HTML
:
331 case FORMAT_GDIMETAFILE
:
332 nFmt
= FORMAT_BITMAP
;
335 case SOT_FORMATSTR_ID_SVXB
:
336 nFmt
= FORMAT_GDIMETAFILE
;
342 rReq
.SetFormat( nFmt
); // try it once more
346 sal_Bool
SvDDEObject::IsPending() const
349 The method determines whether the data-object can be read from a DDE.
351 Returned is the following:
352 ERRCODE_NONE if it has been completely read
353 ERRCODE_SO_PENDING if it has not been completely read
354 ERRCODE_SO_FALSE otherwise
360 sal_Bool
SvDDEObject::IsDataComplete() const
365 IMPL_LINK( SvDDEObject
, ImplGetDDEData
, DdeData
*, pData
)
367 sal_uIntPtr nFmt
= pData
->GetFormat();
370 case FORMAT_GDIMETAFILE
:
378 const sal_Char
* p
= (sal_Char
*)( pData
->operator const void*() );
379 long nLen
= FORMAT_STRING
== nFmt
? (p
? strlen( p
) : 0) : (long)*pData
;
381 Sequence
< sal_Int8
> aSeq( (const sal_Int8
*)p
, nLen
);
384 *pGetData
<<= aSeq
; // Copy Data
385 pGetData
= 0; // reset the pointer here
391 DataChanged( SotExchange::GetFormatMimeType(
392 pData
->GetFormat() ), aVal
);
393 bWaitForData
= sal_False
;
401 IMPL_LINK( SvDDEObject
, ImplDoneDDEData
, void*, pData
)
403 sal_Bool bValid
= (sal_Bool
)(sal_uIntPtr
)pData
;
404 if( !bValid
&& ( pRequest
|| pLink
))
406 DdeTransaction
* pReq
= 0;
407 if( !pLink
|| ( pLink
&& pLink
->IsBusy() ))
408 pReq
= pRequest
; // only the one that is ready
409 else if( pRequest
&& pRequest
->IsBusy() )
410 pReq
= pLink
; // only the one that is ready
414 if( ImplHasOtherFormat( *pReq
) )
418 else if( pReq
== pRequest
)
420 bWaitForData
= sal_False
;
426 bWaitForData
= sal_False
;
433 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */