Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / appl / impldde.cxx
blob9184f57d92e308530388f7c843f9bc761607e0bc
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 ************************************************************************/
30 #if defined(WNT)
31 #include <prewin.h>
32 #include <postwin.h>
33 #endif
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>
46 #include "dde.hrc"
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;
63 namespace sfx2
66 class SvDDELinkEditDialog : public ModalDialog
68 FixedText aFtDdeApp;
69 Edit aEdDdeApp;
70 FixedText aFtDdeTopic;
71 Edit aEdDdeTopic;
72 FixedText aFtDdeItem;
73 Edit aEdDdeItem;
74 FixedLine aGroupDdeChg;
75 OKButton aOKButton1;
76 CancelButton aCancelButton1;
78 DECL_STATIC_LINK( SvDDELinkEditDialog, EditHdl_Impl, Edit* );
79 public:
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 ) )
96 FreeResource();
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() );
116 return sRet;
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() );
125 return 0;
128 SvDDEObject::SvDDEObject()
129 : pConnection( 0 ), pLink( 0 ), pRequest( 0 ), pGetData( 0 ), nError( 0 )
131 SetUpdateTimeout( 100 );
132 bWaitForData = sal_False;
135 SvDDEObject::~SvDDEObject()
137 delete pLink;
138 delete pRequest;
139 delete pConnection;
142 sal_Bool SvDDEObject::GetData( ::com::sun::star::uno::Any & rData /*out param*/,
143 const String & rMimeType,
144 sal_Bool bSynchron )
146 if( !pConnection )
147 return sal_False;
149 if( pConnection->GetError() ) // then we try once more
151 String sServer( pConnection->GetServiceName() );
152 String sTopic( pConnection->GetTopicName() );
154 delete pConnection;
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
161 return sal_False;
163 // Lock against Reentrance
164 bWaitForData = sal_True;
166 // if you want to print, we'll wait until the data is available
167 if( bSynchron )
169 DdeRequest aReq( *pConnection, sItem, 5000 );
170 aReq.SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
171 aReq.SetFormat( SotExchange::GetFormatIdFromMimeType( rMimeType ));
173 pGetData = &rData;
175 do {
176 aReq.Execute();
177 } while( aReq.GetError() && ImplHasOtherFormat( aReq ) );
179 if( pConnection->GetError() )
180 nError = DDELINK_ERROR_DATA;
182 bWaitForData = sal_False;
184 else
186 // otherwise it will be executed asynchronously
188 if( pRequest )
189 delete pRequest;
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(
195 rMimeType ) );
196 pRequest->Execute();
199 ::rtl::OUString aEmptyStr;
200 rData <<= aEmptyStr;
202 return 0 == pConnection->GetError();
206 sal_Bool SvDDEObject::Connect( SvBaseLink * pSvLink )
208 #if defined(WNT)
209 static sal_Bool bInWinExec = sal_False;
210 #endif
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
219 : 0 );
220 AddConnectAdvise( pSvLink );
222 return sal_True;
225 if( !pSvLink->GetLinkManager() )
226 return sal_False;
228 String sServer, sTopic;
229 pSvLink->GetLinkManager()->GetDisplayNames( pSvLink, &sServer, &sTopic, &sItem );
231 if( !sServer.Len() || !sTopic.Len() || !sItem.Len() )
232 return sal_False;
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" ) )
241 sal_Bool bSysTopic;
243 DdeConnection aTmp( sServer, String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "SYSTEM" ) ) );
244 bSysTopic = !aTmp.GetError();
247 if( bSysTopic )
249 nError = DDELINK_ERROR_DATA;
250 return sal_False;
252 // otherwise in Win/WinNT, start the Application directly
255 #if defined(WNT)
257 // Server not up, try once more to start it.
258 if( !bInWinExec )
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;
266 else
268 sal_uInt16 i;
269 for( i=0; i<5; i++ )
271 bInWinExec = sal_True;
272 Application::Reschedule();
273 bInWinExec = sal_False;
275 delete pConnection;
276 pConnection = new DdeConnection( sServer, sTopic );
277 if( !pConnection->GetError() )
278 break;
281 if( i == 5 )
283 nError = DDELINK_ERROR_APP;
287 else
288 #endif // WNT
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() );
301 pLink->Execute();
304 if( pConnection->GetError() )
305 return sal_False;
307 AddDataAdvise( pSvLink,
308 SotExchange::GetFormatMimeType( pSvLink->GetContentType()),
309 LINKUPDATE_ONCALL == nLinkType
310 ? ADVISEMODE_ONLYONCE
311 : 0 );
312 AddConnectAdvise( pSvLink );
313 SetUpdateTimeout( 0 );
314 return sal_True;
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 )
329 sal_uInt16 nFmt = 0;
330 switch( rReq.GetFormat() )
332 case FORMAT_RTF:
333 nFmt = FORMAT_STRING;
334 break;
336 case SOT_FORMATSTR_ID_HTML_SIMPLE:
337 case SOT_FORMATSTR_ID_HTML:
338 nFmt = FORMAT_RTF;
339 break;
341 case FORMAT_GDIMETAFILE:
342 nFmt = FORMAT_BITMAP;
343 break;
345 case SOT_FORMATSTR_ID_SVXB:
346 nFmt = FORMAT_GDIMETAFILE;
347 break;
349 // something else?
351 if( nFmt )
352 rReq.SetFormat( nFmt ); // try it once more
353 return 0 != nFmt;
356 sal_Bool SvDDEObject::IsPending() const
357 /* [Description]
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
367 return bWaitForData;
370 sal_Bool SvDDEObject::IsDataComplete() const
372 return bWaitForData;
375 IMPL_LINK( SvDDEObject, ImplGetDDEData, DdeData*, pData )
377 sal_uIntPtr nFmt = pData->GetFormat();
378 switch( nFmt )
380 case FORMAT_GDIMETAFILE:
381 break;
383 case FORMAT_BITMAP:
384 break;
386 default:
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 );
392 if( pGetData )
394 *pGetData <<= aSeq; // Copy Data
395 pGetData = 0; // reset the pointer here
397 else
399 Any aVal;
400 aVal <<= aSeq;
401 DataChanged( SotExchange::GetFormatMimeType(
402 pData->GetFormat() ), aVal );
403 bWaitForData = sal_False;
408 return 0;
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
422 if( pReq )
424 if( ImplHasOtherFormat( *pReq ) )
426 pReq->Execute();
428 else if( pReq == pRequest )
430 bWaitForData = sal_False;
434 else
435 // End waiting
436 bWaitForData = sal_False;
438 return 0;
443 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */