merge the formfield patch from ooo-build
[ooovba.git] / sfx2 / source / appl / impldde.cxx
blob75df9269684a3b223a9e7ae64e478dd424731ec3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: impldde.cxx,v $
10 * $Revision: 1.9 $
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>
36 #endif
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>
48 #include "dde.hrc"
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
60 #define DDELINK_HOT 1
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;
68 namespace sfx2
71 class SvDDELinkEditDialog : public ModalDialog
73 FixedText aFtDdeApp;
74 Edit aEdDdeApp;
75 FixedText aFtDdeTopic;
76 Edit aEdDdeTopic;
77 FixedText aFtDdeItem;
78 Edit aEdDdeItem;
79 FixedLine aGroupDdeChg;
80 OKButton aOKButton1;
81 CancelButton aCancelButton1;
83 DECL_STATIC_LINK( SvDDELinkEditDialog, EditHdl_Impl, Edit* );
84 public:
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 ) )
101 FreeResource();
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() );
121 return sRet;
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() );
130 return 0;
133 /* \f */
136 SvDDEObject::SvDDEObject()
137 : pConnection( 0 ), pLink( 0 ), pRequest( 0 ), pGetData( 0 ), nError( 0 )
139 SetUpdateTimeout( 100 );
140 bWaitForData = FALSE;
143 SvDDEObject::~SvDDEObject()
145 delete pLink;
146 delete pRequest;
147 delete pConnection;
150 BOOL SvDDEObject::GetData( ::com::sun::star::uno::Any & rData /*out param*/,
151 const String & rMimeType,
152 BOOL bSynchron )
154 if( !pConnection )
155 return FALSE;
157 if( pConnection->GetError() ) // dann versuchen wir es nochmal
159 String sServer( pConnection->GetServiceName() );
160 String sTopic( pConnection->GetTopicName() );
162 delete pConnection;
163 pConnection = new DdeConnection( sServer, sTopic );
164 if( pConnection->GetError() )
165 nError = DDELINK_ERROR_APP;
168 if( bWaitForData ) // wir sind rekursiv drin, wieder raus
169 return FALSE;
171 // Verriegeln gegen Reentrance
172 bWaitForData = TRUE;
174 // falls gedruckt werden soll, warten wir bis die Daten vorhanden sind
175 if( bSynchron )
177 DdeRequest aReq( *pConnection, sItem, 5000 );
178 aReq.SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
179 aReq.SetFormat( SotExchange::GetFormatIdFromMimeType( rMimeType ));
181 pGetData = &rData;
183 do {
184 aReq.Execute();
185 } while( aReq.GetError() && ImplHasOtherFormat( aReq ) );
187 if( pConnection->GetError() )
188 nError = DDELINK_ERROR_DATA;
190 bWaitForData = FALSE;
192 else
194 // ansonsten wird es asynchron ausgefuehrt
195 // if( !pLink || !pLink->IsBusy() )
197 if( pRequest )
198 delete pRequest;
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(
204 rMimeType ) );
205 pRequest->Execute();
208 ::rtl::OUString aEmptyStr;
209 rData <<= aEmptyStr;
211 return 0 == pConnection->GetError();
215 BOOL SvDDEObject::Connect( SvBaseLink * pSvLink )
217 #if defined(WIN) || defined(WNT)
218 static BOOL bInWinExec = FALSE;
219 #endif
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
228 : 0 );
229 AddConnectAdvise( pSvLink );
231 return TRUE;
234 if( !pSvLink->GetLinkManager() )
235 return FALSE;
237 String sServer, sTopic;
238 pSvLink->GetLinkManager()->GetDisplayNames( pSvLink, &sServer, &sTopic, &sItem );
240 if( !sServer.Len() || !sTopic.Len() || !sItem.Len() )
241 return FALSE;
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" ) )
250 BOOL bSysTopic;
252 DdeConnection aTmp( sServer, String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "SYSTEM" ) ) );
253 bSysTopic = !aTmp.GetError();
256 if( bSysTopic )
258 nError = DDELINK_ERROR_DATA;
259 return FALSE;
261 // ansonsten unter Win/WinNT die Applikation direkt starten
264 #if defined(WIN) || defined(WNT)
266 // Server nicht da, starten und nochmal versuchen
267 if( !bInWinExec )
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;
275 else
277 USHORT i;
278 for( i=0; i<5; i++ )
280 bInWinExec = TRUE;
281 Application::Reschedule();
282 bInWinExec = FALSE;
284 delete pConnection;
285 pConnection = new DdeConnection( sServer, sTopic );
286 if( !pConnection->GetError() )
287 break;
290 if( i == 5 )
292 nError = DDELINK_ERROR_APP;
296 else
297 #endif // WIN / WNT
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() );
310 pLink->Execute();
313 if( pConnection->GetError() )
314 return FALSE;
316 AddDataAdvise( pSvLink,
317 SotExchange::GetFormatMimeType( pSvLink->GetContentType()),
318 LINKUPDATE_ONCALL == nLinkType
319 ? ADVISEMODE_ONLYONCE
320 : 0 );
321 AddConnectAdvise( pSvLink );
322 SetUpdateTimeout( 0 );
323 return TRUE;
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 )
338 USHORT nFmt = 0;
339 switch( rReq.GetFormat() )
341 case FORMAT_RTF:
342 nFmt = FORMAT_STRING;
343 break;
345 case SOT_FORMATSTR_ID_HTML_SIMPLE:
346 case SOT_FORMATSTR_ID_HTML:
347 nFmt = FORMAT_RTF;
348 break;
350 case FORMAT_GDIMETAFILE:
351 nFmt = FORMAT_BITMAP;
352 break;
354 case SOT_FORMATSTR_ID_SVXB:
355 nFmt = FORMAT_GDIMETAFILE;
356 break;
358 // sonst noch irgendwas ??
360 if( nFmt )
361 rReq.SetFormat( nFmt ); // damit nochmal versuchen
362 return 0 != nFmt;
365 BOOL SvDDEObject::IsPending() const
366 /* [Beschreibung]
368 Die Methode stellt fest, ob aus einem DDE-Object die Daten gelesen
369 werden kann.
370 Zurueckgegeben wird:
371 ERRCODE_NONE wenn sie komplett gelesen wurde
372 ERRCODE_SO_PENDING wenn sie noch nicht komplett gelesen wurde
373 ERRCODE_SO_FALSE sonst
376 return bWaitForData;
379 BOOL SvDDEObject::IsDataComplete() const
381 return bWaitForData;
384 IMPL_LINK( SvDDEObject, ImplGetDDEData, DdeData*, pData )
386 ULONG nFmt = pData->GetFormat();
387 switch( nFmt )
389 case FORMAT_GDIMETAFILE:
390 break;
392 case FORMAT_BITMAP:
393 break;
395 default:
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 );
401 if( pGetData )
403 *pGetData <<= aSeq; // Daten kopieren
404 pGetData = 0; // und den Pointer bei mir zuruecksetzen
406 else
408 Any aVal;
409 aVal <<= aSeq;
410 DataChanged( SotExchange::GetFormatMimeType(
411 pData->GetFormat() ), aVal );
412 bWaitForData = FALSE;
417 return 0;
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
431 if( pReq )
433 if( ImplHasOtherFormat( *pReq ) )
435 pReq->Execute();
437 else if( pReq == pRequest )
439 // das wars dann
440 bWaitForData = FALSE;
444 else
445 // das warten ist beendet
446 bWaitForData = FALSE;
448 return 0;