bump product version to 4.2.0.1
[LibreOffice.git] / sfx2 / source / appl / impldde.cxx
blobcc6431d0bd3a030d34ac31efcf03cc5010dc3973
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #if defined(WNT)
22 #include <prewin.h>
23 #include <postwin.h>
24 #endif
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>
37 #include "dde.hrc"
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;
53 namespace sfx2
56 class SvDDELinkEditDialog : public ModalDialog
58 FixedText aFtDdeApp;
59 Edit aEdDdeApp;
60 FixedText aFtDdeTopic;
61 Edit aEdDdeTopic;
62 FixedText aFtDdeItem;
63 Edit aEdDdeItem;
64 FixedLine aGroupDdeChg;
65 OKButton aOKButton1;
66 CancelButton aCancelButton1;
68 DECL_STATIC_LINK( SvDDELinkEditDialog, EditHdl_Impl, Edit* );
69 public:
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 ) )
86 FreeResource();
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() );
106 return sRet;
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() );
115 return 0;
118 SvDDEObject::SvDDEObject()
119 : pConnection( 0 ), pLink( 0 ), pRequest( 0 ), pGetData( 0 ), nError( 0 )
121 SetUpdateTimeout( 100 );
122 bWaitForData = sal_False;
125 SvDDEObject::~SvDDEObject()
127 delete pLink;
128 delete pRequest;
129 delete pConnection;
132 sal_Bool SvDDEObject::GetData( ::com::sun::star::uno::Any & rData /*out param*/,
133 const OUString & rMimeType,
134 sal_Bool bSynchron )
136 if( !pConnection )
137 return sal_False;
139 if( pConnection->GetError() ) // then we try once more
141 OUString sServer( pConnection->GetServiceName() );
142 OUString sTopic( pConnection->GetTopicName() );
144 delete pConnection;
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
151 return sal_False;
153 // Lock against Reentrance
154 bWaitForData = sal_True;
156 // if you want to print, we'll wait until the data is available
157 if( bSynchron )
159 DdeRequest aReq( *pConnection, sItem, 5000 );
160 aReq.SetDataHdl( LINK( this, SvDDEObject, ImplGetDDEData ) );
161 aReq.SetFormat( SotExchange::GetFormatIdFromMimeType( rMimeType ));
163 pGetData = &rData;
165 do {
166 aReq.Execute();
167 } while( aReq.GetError() && ImplHasOtherFormat( aReq ) );
169 if( pConnection->GetError() )
170 nError = DDELINK_ERROR_DATA;
172 bWaitForData = sal_False;
174 else
176 // otherwise it will be executed asynchronously
178 if( pRequest )
179 delete pRequest;
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(
185 rMimeType ) );
186 pRequest->Execute();
189 OUString aEmptyStr;
190 rData <<= aEmptyStr;
192 return 0 == pConnection->GetError();
196 sal_Bool SvDDEObject::Connect( SvBaseLink * pSvLink )
198 #if defined(WNT)
199 static sal_Bool bInWinExec = sal_False;
200 #endif
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
209 : 0 );
210 AddConnectAdvise( pSvLink );
212 return sal_True;
215 if( !pSvLink->GetLinkManager() )
216 return sal_False;
218 OUString sServer, sTopic;
219 pSvLink->GetLinkManager()->GetDisplayNames( pSvLink, &sServer, &sTopic, &sItem );
221 if( sServer.isEmpty() || sTopic.isEmpty() || sItem.isEmpty() )
222 return sal_False;
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" ) )
231 sal_Bool bSysTopic;
233 DdeConnection aTmp(sServer, OUString("SYSTEM"));
234 bSysTopic = !aTmp.GetError();
237 if( bSysTopic )
239 nError = DDELINK_ERROR_DATA;
240 return sal_False;
242 // otherwise in Win/WinNT, start the Application directly
245 #if defined(WNT)
247 // Server not up, try once more to start it.
248 if( !bInWinExec )
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;
256 else
258 sal_uInt16 i;
259 for( i=0; i<5; i++ )
261 bInWinExec = sal_True;
262 Application::Reschedule();
263 bInWinExec = sal_False;
265 delete pConnection;
266 pConnection = new DdeConnection( sServer, sTopic );
267 if( !pConnection->GetError() )
268 break;
271 if( i == 5 )
273 nError = DDELINK_ERROR_APP;
277 else
278 #endif // WNT
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() );
291 pLink->Execute();
294 if( pConnection->GetError() )
295 return sal_False;
297 AddDataAdvise( pSvLink,
298 SotExchange::GetFormatMimeType( pSvLink->GetContentType()),
299 LINKUPDATE_ONCALL == nLinkType
300 ? ADVISEMODE_ONLYONCE
301 : 0 );
302 AddConnectAdvise( pSvLink );
303 SetUpdateTimeout( 0 );
304 return sal_True;
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 )
319 sal_uInt16 nFmt = 0;
320 switch( rReq.GetFormat() )
322 case FORMAT_RTF:
323 nFmt = FORMAT_STRING;
324 break;
326 case SOT_FORMATSTR_ID_HTML_SIMPLE:
327 case SOT_FORMATSTR_ID_HTML:
328 nFmt = FORMAT_RTF;
329 break;
331 case FORMAT_GDIMETAFILE:
332 nFmt = FORMAT_BITMAP;
333 break;
335 case SOT_FORMATSTR_ID_SVXB:
336 nFmt = FORMAT_GDIMETAFILE;
337 break;
339 // something else?
341 if( nFmt )
342 rReq.SetFormat( nFmt ); // try it once more
343 return 0 != nFmt;
346 sal_Bool SvDDEObject::IsPending() const
347 /* [Description]
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
357 return bWaitForData;
360 sal_Bool SvDDEObject::IsDataComplete() const
362 return bWaitForData;
365 IMPL_LINK( SvDDEObject, ImplGetDDEData, DdeData*, pData )
367 sal_uIntPtr nFmt = pData->GetFormat();
368 switch( nFmt )
370 case FORMAT_GDIMETAFILE:
371 break;
373 case FORMAT_BITMAP:
374 break;
376 default:
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 );
382 if( pGetData )
384 *pGetData <<= aSeq; // Copy Data
385 pGetData = 0; // reset the pointer here
387 else
389 Any aVal;
390 aVal <<= aSeq;
391 DataChanged( SotExchange::GetFormatMimeType(
392 pData->GetFormat() ), aVal );
393 bWaitForData = sal_False;
398 return 0;
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
412 if( pReq )
414 if( ImplHasOtherFormat( *pReq ) )
416 pReq->Execute();
418 else if( pReq == pRequest )
420 bWaitForData = sal_False;
424 else
425 // End waiting
426 bWaitForData = sal_False;
428 return 0;
433 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */