1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
35 #include "impldde.hxx"
37 #include <vcl/svapp.hxx>
38 #include <vcl/fixed.hxx>
39 #include <vcl/edit.hxx>
40 #include <vcl/button.hxx>
41 #include <vcl/msgbox.hxx>
42 #include <sot/exchange.hxx>
43 #include <rtl/strbuf.hxx>
44 #include <rtl/ustring.hxx>
47 #include <sfx2/lnkbase.hxx>
48 #include <sfx2/linkmgr.hxx>
49 #include "sfx2/sfxresid.hxx"
51 #include <com/sun/star/uno/Any.hxx>
52 #include <com/sun/star/uno/Sequence.hxx>
54 #include <svl/svdde.hxx>
55 #include <sot/formats.hxx>
57 #define DDELINK_ERROR_APP 1
58 #define DDELINK_ERROR_DATA 2
59 #define DDELINK_ERROR_LINK 3
61 using namespace ::com::sun::star::uno
;
66 class SvDDELinkEditDialog
: public ModalDialog
70 FixedText aFtDdeTopic
;
74 FixedLine aGroupDdeChg
;
76 CancelButton aCancelButton1
;
78 DECL_STATIC_LINK( SvDDELinkEditDialog
, EditHdl_Impl
, Edit
* );
80 SvDDELinkEditDialog( Window
* pParent
, SvBaseLink
* );
81 String
GetCmd() const;
84 SvDDELinkEditDialog::SvDDELinkEditDialog( Window
* pParent
, SvBaseLink
* pLink
)
85 : ModalDialog( pParent
, SfxResId( MD_DDE_LINKEDIT
) ),
86 aFtDdeApp( this, SfxResId( FT_DDE_APP
) ),
87 aEdDdeApp( this, SfxResId( ED_DDE_APP
) ),
88 aFtDdeTopic( this, SfxResId( FT_DDE_TOPIC
) ),
89 aEdDdeTopic( this, SfxResId( ED_DDE_TOPIC
) ),
90 aFtDdeItem( this, SfxResId( FT_DDE_ITEM
) ),
91 aEdDdeItem( this, SfxResId( ED_DDE_ITEM
) ),
92 aGroupDdeChg( this, SfxResId( GROUP_DDE_CHG
) ),
93 aOKButton1( this, SfxResId( 1 ) ),
94 aCancelButton1( this, SfxResId( 1 ) )
98 String sServer
, sTopic
, sItem
;
99 pLink
->GetLinkManager()->GetDisplayNames( pLink
, &sServer
, &sTopic
, &sItem
);
101 aEdDdeApp
.SetText( sServer
);
102 aEdDdeTopic
.SetText( sTopic
);
103 aEdDdeItem
.SetText( sItem
);
105 aEdDdeApp
.SetModifyHdl( STATIC_LINK( this, SvDDELinkEditDialog
, EditHdl_Impl
));
106 aEdDdeTopic
.SetModifyHdl( STATIC_LINK( this, SvDDELinkEditDialog
, EditHdl_Impl
));
107 aEdDdeItem
.SetModifyHdl( STATIC_LINK( this, SvDDELinkEditDialog
, EditHdl_Impl
));
109 aOKButton1
.Enable( sServer
.Len() && sTopic
.Len() && sItem
.Len() );
112 String
SvDDELinkEditDialog::GetCmd() const
114 String
sCmd( aEdDdeApp
.GetText() ), sRet
;
115 ::sfx2::MakeLnkName( sRet
, &sCmd
, aEdDdeTopic
.GetText(), aEdDdeItem
.GetText() );
119 IMPL_STATIC_LINK( SvDDELinkEditDialog
, EditHdl_Impl
, Edit
*, pEdit
)
121 (void)pEdit
; // unused variable
122 pThis
->aOKButton1
.Enable( pThis
->aEdDdeApp
.GetText().Len() &&
123 pThis
->aEdDdeTopic
.GetText().Len() &&
124 pThis
->aEdDdeItem
.GetText().Len() );
128 SvDDEObject::SvDDEObject()
129 : pConnection( 0 ), pLink( 0 ), pRequest( 0 ), pGetData( 0 ), nError( 0 )
131 SetUpdateTimeout( 100 );
132 bWaitForData
= sal_False
;
135 SvDDEObject::~SvDDEObject()
142 sal_Bool
SvDDEObject::GetData( ::com::sun::star::uno::Any
& rData
/*out param*/,
143 const String
& rMimeType
,
149 if( pConnection
->GetError() ) // then we try once more
151 String
sServer( pConnection
->GetServiceName() );
152 String
sTopic( pConnection
->GetTopicName() );
155 pConnection
= new DdeConnection( sServer
, sTopic
);
156 if( pConnection
->GetError() )
157 nError
= DDELINK_ERROR_APP
;
160 if( bWaitForData
) // we are in an rekursive loop, get out again
163 // Lock against Reentrance
164 bWaitForData
= sal_True
;
166 // if you want to print, we'll wait until the data is available
169 DdeRequest
aReq( *pConnection
, sItem
, 5000 );
170 aReq
.SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
171 aReq
.SetFormat( SotExchange::GetFormatIdFromMimeType( rMimeType
));
177 } while( aReq
.GetError() && ImplHasOtherFormat( aReq
) );
179 if( pConnection
->GetError() )
180 nError
= DDELINK_ERROR_DATA
;
182 bWaitForData
= sal_False
;
186 // otherwise it will be executed asynchronously
191 pRequest
= new DdeRequest( *pConnection
, sItem
);
192 pRequest
->SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
193 pRequest
->SetDoneHdl( LINK( this, SvDDEObject
, ImplDoneDDEData
) );
194 pRequest
->SetFormat( SotExchange::GetFormatIdFromMimeType(
199 ::rtl::OUString aEmptyStr
;
202 return 0 == pConnection
->GetError();
206 sal_Bool
SvDDEObject::Connect( SvBaseLink
* pSvLink
)
209 static sal_Bool bInWinExec
= sal_False
;
211 sal_uInt16 nLinkType
= pSvLink
->GetUpdateMode();
212 if( pConnection
) // Connection is already made
214 // well, then just add it as dependent
215 AddDataAdvise( pSvLink
,
216 SotExchange::GetFormatMimeType( pSvLink
->GetContentType()),
217 LINKUPDATE_ONCALL
== nLinkType
218 ? ADVISEMODE_ONLYONCE
220 AddConnectAdvise( pSvLink
);
225 if( !pSvLink
->GetLinkManager() )
228 String sServer
, sTopic
;
229 pSvLink
->GetLinkManager()->GetDisplayNames( pSvLink
, &sServer
, &sTopic
, &sItem
);
231 if( !sServer
.Len() || !sTopic
.Len() || !sItem
.Len() )
234 pConnection
= new DdeConnection( sServer
, sTopic
);
235 if( pConnection
->GetError() )
237 // Is it possible to address the system-Topic?
238 // then the server is up, it just does not know the topic!
239 if( sTopic
.EqualsIgnoreCaseAscii( "SYSTEM" ) )
243 DdeConnection
aTmp( sServer
, String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "SYSTEM" ) ) );
244 bSysTopic
= !aTmp
.GetError();
249 nError
= DDELINK_ERROR_DATA
;
252 // otherwise in Win/WinNT, start the Application directly
257 // Server not up, try once more to start it.
260 rtl::OStringBuffer
aCmdLine(rtl::OUStringToOString(sServer
, RTL_TEXTENCODING_ASCII_US
));
261 aCmdLine
.append(RTL_CONSTASCII_STRINGPARAM(".exe "));
262 aCmdLine
.append(rtl::OUStringToOString(sTopic
, RTL_TEXTENCODING_ASCII_US
));
264 if( WinExec( aCmdLine
.getStr(), SW_SHOWMINIMIZED
) < 32 )
265 nError
= DDELINK_ERROR_APP
;
271 bInWinExec
= sal_True
;
272 Application::Reschedule();
273 bInWinExec
= sal_False
;
276 pConnection
= new DdeConnection( sServer
, sTopic
);
277 if( !pConnection
->GetError() )
283 nError
= DDELINK_ERROR_APP
;
290 nError
= DDELINK_ERROR_APP
;
294 if( LINKUPDATE_ALWAYS
== nLinkType
&& !pLink
&& !pConnection
->GetError() )
296 // Setting up Hot Link, Data will be available at some point later on
297 pLink
= new DdeHotLink( *pConnection
, sItem
);
298 pLink
->SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
299 pLink
->SetDoneHdl( LINK( this, SvDDEObject
, ImplDoneDDEData
) );
300 pLink
->SetFormat( pSvLink
->GetContentType() );
304 if( pConnection
->GetError() )
307 AddDataAdvise( pSvLink
,
308 SotExchange::GetFormatMimeType( pSvLink
->GetContentType()),
309 LINKUPDATE_ONCALL
== nLinkType
310 ? ADVISEMODE_ONLYONCE
312 AddConnectAdvise( pSvLink
);
313 SetUpdateTimeout( 0 );
317 void SvDDEObject::Edit( Window
* pParent
, sfx2::SvBaseLink
* pBaseLink
, const Link
& rEndEditHdl
)
319 SvDDELinkEditDialog
aDlg( pParent
, pBaseLink
);
320 if ( RET_OK
== aDlg
.Execute() && rEndEditHdl
.IsSet() )
322 String sCommand
= aDlg
.GetCmd();
323 rEndEditHdl
.Call( &sCommand
);
327 sal_Bool
SvDDEObject::ImplHasOtherFormat( DdeTransaction
& rReq
)
330 switch( rReq
.GetFormat() )
333 nFmt
= FORMAT_STRING
;
336 case SOT_FORMATSTR_ID_HTML_SIMPLE
:
337 case SOT_FORMATSTR_ID_HTML
:
341 case FORMAT_GDIMETAFILE
:
342 nFmt
= FORMAT_BITMAP
;
345 case SOT_FORMATSTR_ID_SVXB
:
346 nFmt
= FORMAT_GDIMETAFILE
;
352 rReq
.SetFormat( nFmt
); // try it once more
356 sal_Bool
SvDDEObject::IsPending() const
359 The method determines whether the data-object can be read from a DDE.
361 Returned is the following:
362 ERRCODE_NONE if it has been completely read
363 ERRCODE_SO_PENDING if it has not been completely read
364 ERRCODE_SO_FALSE otherwise
370 sal_Bool
SvDDEObject::IsDataComplete() const
375 IMPL_LINK( SvDDEObject
, ImplGetDDEData
, DdeData
*, pData
)
377 sal_uIntPtr nFmt
= pData
->GetFormat();
380 case FORMAT_GDIMETAFILE
:
388 const sal_Char
* p
= (sal_Char
*)( pData
->operator const void*() );
389 long nLen
= FORMAT_STRING
== nFmt
? (p
? strlen( p
) : 0) : (long)*pData
;
391 Sequence
< sal_Int8
> aSeq( (const sal_Int8
*)p
, nLen
);
394 *pGetData
<<= aSeq
; // Copy Data
395 pGetData
= 0; // reset the pointer here
401 DataChanged( SotExchange::GetFormatMimeType(
402 pData
->GetFormat() ), aVal
);
403 bWaitForData
= sal_False
;
411 IMPL_LINK( SvDDEObject
, ImplDoneDDEData
, void*, pData
)
413 sal_Bool bValid
= (sal_Bool
)(sal_uIntPtr
)pData
;
414 if( !bValid
&& ( pRequest
|| pLink
))
416 DdeTransaction
* pReq
= 0;
417 if( !pLink
|| ( pLink
&& pLink
->IsBusy() ))
418 pReq
= pRequest
; // only the one that is ready
419 else if( pRequest
&& pRequest
->IsBusy() )
420 pReq
= pLink
; // only the one that is ready
424 if( ImplHasOtherFormat( *pReq
) )
428 else if( pReq
== pRequest
)
430 bWaitForData
= sal_False
;
436 bWaitForData
= sal_False
;
443 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */