1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: impldde.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #if defined(WIN) || defined(WNT)
35 #include <tools/svwin.h>
38 #include "impldde.hxx"
40 #include <vcl/svapp.hxx>
41 #include <vcl/fixed.hxx>
42 #include <vcl/edit.hxx>
43 #include <vcl/button.hxx>
44 #include <vcl/msgbox.hxx>
45 #include <sot/exchange.hxx>
46 #include <rtl/ustring.hxx>
49 #include <sfx2/lnkbase.hxx>
50 #include <sfx2/linkmgr.hxx>
51 #include "sfxresid.hxx"
53 #include <com/sun/star/uno/Any.hxx>
54 #include <com/sun/star/uno/Sequence.hxx>
56 #include <svtools/svdde.hxx>
57 #include <sot/formats.hxx>
59 #define DDELINK_COLD 0
62 #define DDELINK_ERROR_APP 1
63 #define DDELINK_ERROR_DATA 2
64 #define DDELINK_ERROR_LINK 3
66 using namespace ::com::sun::star::uno
;
71 class SvDDELinkEditDialog
: public ModalDialog
75 FixedText aFtDdeTopic
;
79 FixedLine aGroupDdeChg
;
81 CancelButton aCancelButton1
;
83 DECL_STATIC_LINK( SvDDELinkEditDialog
, EditHdl_Impl
, Edit
* );
85 SvDDELinkEditDialog( Window
* pParent
, SvBaseLink
* );
86 String
GetCmd() const;
89 SvDDELinkEditDialog::SvDDELinkEditDialog( Window
* pParent
, SvBaseLink
* pLink
)
90 : ModalDialog( pParent
, SfxResId( MD_DDE_LINKEDIT
) ),
91 aFtDdeApp( this, SfxResId( FT_DDE_APP
) ),
92 aEdDdeApp( this, SfxResId( ED_DDE_APP
) ),
93 aFtDdeTopic( this, SfxResId( FT_DDE_TOPIC
) ),
94 aEdDdeTopic( this, SfxResId( ED_DDE_TOPIC
) ),
95 aFtDdeItem( this, SfxResId( FT_DDE_ITEM
) ),
96 aEdDdeItem( this, SfxResId( ED_DDE_ITEM
) ),
97 aGroupDdeChg( this, SfxResId( GROUP_DDE_CHG
) ),
98 aOKButton1( this, SfxResId( 1 ) ),
99 aCancelButton1( this, SfxResId( 1 ) )
103 String sServer
, sTopic
, sItem
;
104 pLink
->GetLinkManager()->GetDisplayNames( pLink
, &sServer
, &sTopic
, &sItem
);
106 aEdDdeApp
.SetText( sServer
);
107 aEdDdeTopic
.SetText( sTopic
);
108 aEdDdeItem
.SetText( sItem
);
110 aEdDdeApp
.SetModifyHdl( STATIC_LINK( this, SvDDELinkEditDialog
, EditHdl_Impl
));
111 aEdDdeTopic
.SetModifyHdl( STATIC_LINK( this, SvDDELinkEditDialog
, EditHdl_Impl
));
112 aEdDdeItem
.SetModifyHdl( STATIC_LINK( this, SvDDELinkEditDialog
, EditHdl_Impl
));
114 aOKButton1
.Enable( sServer
.Len() && sTopic
.Len() && sItem
.Len() );
117 String
SvDDELinkEditDialog::GetCmd() const
119 String
sCmd( aEdDdeApp
.GetText() ), sRet
;
120 ::sfx2::MakeLnkName( sRet
, &sCmd
, aEdDdeTopic
.GetText(), aEdDdeItem
.GetText() );
124 IMPL_STATIC_LINK( SvDDELinkEditDialog
, EditHdl_Impl
, Edit
*, pEdit
)
126 (void)pEdit
; // unused variable
127 pThis
->aOKButton1
.Enable( pThis
->aEdDdeApp
.GetText().Len() &&
128 pThis
->aEdDdeTopic
.GetText().Len() &&
129 pThis
->aEdDdeItem
.GetText().Len() );
136 SvDDEObject::SvDDEObject()
137 : pConnection( 0 ), pLink( 0 ), pRequest( 0 ), pGetData( 0 ), nError( 0 )
139 SetUpdateTimeout( 100 );
140 bWaitForData
= FALSE
;
143 SvDDEObject::~SvDDEObject()
150 BOOL
SvDDEObject::GetData( ::com::sun::star::uno::Any
& rData
/*out param*/,
151 const String
& rMimeType
,
157 if( pConnection
->GetError() ) // dann versuchen wir es nochmal
159 String
sServer( pConnection
->GetServiceName() );
160 String
sTopic( pConnection
->GetTopicName() );
163 pConnection
= new DdeConnection( sServer
, sTopic
);
164 if( pConnection
->GetError() )
165 nError
= DDELINK_ERROR_APP
;
168 if( bWaitForData
) // wir sind rekursiv drin, wieder raus
171 // Verriegeln gegen Reentrance
174 // falls gedruckt werden soll, warten wir bis die Daten vorhanden sind
177 DdeRequest
aReq( *pConnection
, sItem
, 5000 );
178 aReq
.SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
179 aReq
.SetFormat( SotExchange::GetFormatIdFromMimeType( rMimeType
));
185 } while( aReq
.GetError() && ImplHasOtherFormat( aReq
) );
187 if( pConnection
->GetError() )
188 nError
= DDELINK_ERROR_DATA
;
190 bWaitForData
= FALSE
;
194 // ansonsten wird es asynchron ausgefuehrt
195 // if( !pLink || !pLink->IsBusy() )
200 pRequest
= new DdeRequest( *pConnection
, sItem
);
201 pRequest
->SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
202 pRequest
->SetDoneHdl( LINK( this, SvDDEObject
, ImplDoneDDEData
) );
203 pRequest
->SetFormat( SotExchange::GetFormatIdFromMimeType(
208 ::rtl::OUString aEmptyStr
;
211 return 0 == pConnection
->GetError();
215 BOOL
SvDDEObject::Connect( SvBaseLink
* pSvLink
)
217 #if defined(WIN) || defined(WNT)
218 static BOOL bInWinExec
= FALSE
;
220 USHORT nLinkType
= pSvLink
->GetUpdateMode();
221 if( pConnection
) // Verbindung steht ja schon
223 // tja, dann nur noch als Abhaengig eintragen
224 AddDataAdvise( pSvLink
,
225 SotExchange::GetFormatMimeType( pSvLink
->GetContentType()),
226 LINKUPDATE_ONCALL
== nLinkType
227 ? ADVISEMODE_ONLYONCE
229 AddConnectAdvise( pSvLink
);
234 if( !pSvLink
->GetLinkManager() )
237 String sServer
, sTopic
;
238 pSvLink
->GetLinkManager()->GetDisplayNames( pSvLink
, &sServer
, &sTopic
, &sItem
);
240 if( !sServer
.Len() || !sTopic
.Len() || !sItem
.Len() )
243 pConnection
= new DdeConnection( sServer
, sTopic
);
244 if( pConnection
->GetError() )
246 // kann man denn das System-Topic ansprechen ?
247 // dann ist der Server oben, kennt nur nicht das Topic!
248 if( sTopic
.EqualsIgnoreCaseAscii( "SYSTEM" ) )
252 DdeConnection
aTmp( sServer
, String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "SYSTEM" ) ) );
253 bSysTopic
= !aTmp
.GetError();
258 nError
= DDELINK_ERROR_DATA
;
261 // ansonsten unter Win/WinNT die Applikation direkt starten
264 #if defined(WIN) || defined(WNT)
266 // Server nicht da, starten und nochmal versuchen
269 ByteString
aCmdLine( sServer
, RTL_TEXTENCODING_ASCII_US
);
270 aCmdLine
.Append( ".exe " );
271 aCmdLine
.Append( ByteString( sTopic
, RTL_TEXTENCODING_ASCII_US
) );
273 if( WinExec( aCmdLine
.GetBuffer(), SW_SHOWMINIMIZED
) < 32 )
274 nError
= DDELINK_ERROR_APP
;
281 Application::Reschedule();
285 pConnection
= new DdeConnection( sServer
, sTopic
);
286 if( !pConnection
->GetError() )
292 nError
= DDELINK_ERROR_APP
;
299 nError
= DDELINK_ERROR_APP
;
303 if( LINKUPDATE_ALWAYS
== nLinkType
&& !pLink
&& !pConnection
->GetError() )
305 // Hot Link einrichten, Daten kommen irgendwann spaeter
306 pLink
= new DdeHotLink( *pConnection
, sItem
);
307 pLink
->SetDataHdl( LINK( this, SvDDEObject
, ImplGetDDEData
) );
308 pLink
->SetDoneHdl( LINK( this, SvDDEObject
, ImplDoneDDEData
) );
309 pLink
->SetFormat( pSvLink
->GetContentType() );
313 if( pConnection
->GetError() )
316 AddDataAdvise( pSvLink
,
317 SotExchange::GetFormatMimeType( pSvLink
->GetContentType()),
318 LINKUPDATE_ONCALL
== nLinkType
319 ? ADVISEMODE_ONLYONCE
321 AddConnectAdvise( pSvLink
);
322 SetUpdateTimeout( 0 );
326 void SvDDEObject::Edit( Window
* pParent
, sfx2::SvBaseLink
* pBaseLink
, const Link
& rEndEditHdl
)
328 SvDDELinkEditDialog
aDlg( pParent
, pBaseLink
);
329 if ( RET_OK
== aDlg
.Execute() && rEndEditHdl
.IsSet() )
331 String sCommand
= aDlg
.GetCmd();
332 rEndEditHdl
.Call( &sCommand
);
336 BOOL
SvDDEObject::ImplHasOtherFormat( DdeTransaction
& rReq
)
339 switch( rReq
.GetFormat() )
342 nFmt
= FORMAT_STRING
;
345 case SOT_FORMATSTR_ID_HTML_SIMPLE
:
346 case SOT_FORMATSTR_ID_HTML
:
350 case FORMAT_GDIMETAFILE
:
351 nFmt
= FORMAT_BITMAP
;
354 case SOT_FORMATSTR_ID_SVXB
:
355 nFmt
= FORMAT_GDIMETAFILE
;
358 // sonst noch irgendwas ??
361 rReq
.SetFormat( nFmt
); // damit nochmal versuchen
365 BOOL
SvDDEObject::IsPending() const
368 Die Methode stellt fest, ob aus einem DDE-Object die Daten gelesen
371 ERRCODE_NONE wenn sie komplett gelesen wurde
372 ERRCODE_SO_PENDING wenn sie noch nicht komplett gelesen wurde
373 ERRCODE_SO_FALSE sonst
379 BOOL
SvDDEObject::IsDataComplete() const
384 IMPL_LINK( SvDDEObject
, ImplGetDDEData
, DdeData
*, pData
)
386 ULONG nFmt
= pData
->GetFormat();
389 case FORMAT_GDIMETAFILE
:
397 const sal_Char
* p
= (sal_Char
*)( pData
->operator const void*() );
398 long nLen
= FORMAT_STRING
== nFmt
? (p
? strlen( p
) : 0) : (long)*pData
;
400 Sequence
< sal_Int8
> aSeq( (const sal_Int8
*)p
, nLen
);
403 *pGetData
<<= aSeq
; // Daten kopieren
404 pGetData
= 0; // und den Pointer bei mir zuruecksetzen
410 DataChanged( SotExchange::GetFormatMimeType(
411 pData
->GetFormat() ), aVal
);
412 bWaitForData
= FALSE
;
420 IMPL_LINK( SvDDEObject
, ImplDoneDDEData
, void*, pData
)
422 BOOL bValid
= (BOOL
)(ULONG
)pData
;
423 if( !bValid
&& ( pRequest
|| pLink
))
425 DdeTransaction
* pReq
= 0;
426 if( !pLink
|| ( pLink
&& pLink
->IsBusy() ))
427 pReq
= pRequest
; // dann kann nur der fertig sein
428 else if( pRequest
&& pRequest
->IsBusy() )
429 pReq
= pLink
; // dann kann nur der fertig sein
433 if( ImplHasOtherFormat( *pReq
) )
437 else if( pReq
== pRequest
)
440 bWaitForData
= FALSE
;
445 // das warten ist beendet
446 bWaitForData
= FALSE
;