merge the formfield patch from ooo-build
[ooovba.git] / sfx2 / source / appl / appdde.cxx
blob45e1e23d5500df49051c507fe34fddff66ce35bb
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: appdde.cxx,v $
10 * $Revision: 1.19.142.1 $
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"
33 #include <vcl/wrkwin.hxx>
34 #include <svtools/rectitem.hxx>
35 #include <svtools/eitem.hxx>
36 #include <svtools/intitem.hxx>
37 #include <basic/sbstar.hxx>
38 #include <svtools/stritem.hxx>
39 #include <svtools/svdde.hxx>
40 #include <sfx2/lnkbase.hxx>
41 #include <sfx2/linkmgr.hxx>
43 #include <tools/urlobj.hxx>
44 #include <svtools/pathoptions.hxx>
45 #ifndef GCC
46 #endif
48 #include <sfx2/app.hxx>
49 #include "appdata.hxx"
50 #include <sfx2/objsh.hxx>
51 #include <sfx2/viewfrm.hxx>
52 #include <sfx2/topfrm.hxx>
53 #include <sfx2/dispatch.hxx>
54 #include "sfxtypes.hxx"
55 #include <sfx2/sfxsids.hrc>
56 #include "helper.hxx"
57 #include <sfx2/docfile.hxx>
59 //========================================================================
61 String SfxDdeServiceName_Impl( const String& sIn )
63 ByteString sTemp = U2S( sIn );
64 ByteString sReturn;
66 for ( sal_uInt16 n = sTemp.Len(); n; --n )
67 if ( sTemp.Copy( n-1, 1 ).IsAlphaNumericAscii() )
68 sReturn += sTemp.GetChar(n-1);
70 return S2U( sReturn );
74 class ImplDdeService : public DdeService
76 public:
77 ImplDdeService( const String& rNm )
78 : DdeService( rNm )
80 virtual BOOL MakeTopic( const String& );
82 virtual String Topics();
83 // virtual String Formats();
84 // virtual String SysItems();
85 // virtual String Status();
87 virtual BOOL SysTopicExecute( const String* pStr );
90 class SfxDdeTriggerTopic_Impl : public DdeTopic
92 public:
93 SfxDdeTriggerTopic_Impl()
94 : DdeTopic( DEFINE_CONST_UNICODE("TRIGGER") )
97 virtual BOOL Execute( const String* );
100 class SfxDdeDocTopic_Impl : public DdeTopic
102 public:
103 SfxObjectShell* pSh;
104 DdeData aData;
105 ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
107 SfxDdeDocTopic_Impl( SfxObjectShell* pShell )
108 : DdeTopic( pShell->GetTitle(SFX_TITLE_FULLNAME) ), pSh( pShell )
111 virtual DdeData* Get( ULONG );
112 virtual BOOL Put( const DdeData* );
113 virtual BOOL Execute( const String* );
114 virtual BOOL StartAdviseLoop();
115 virtual BOOL MakeItem( const String& rItem );
117 // wird benoetigt?
118 // virtual void Connect( long n );
119 // virtual void Disconnect( long n );
120 // virtual void StopAdviseLoop();
125 SV_DECL_PTRARR( SfxDdeDocTopics_Impl, SfxDdeDocTopic_Impl *, 4, 4 )
126 SV_IMPL_PTRARR( SfxDdeDocTopics_Impl, SfxDdeDocTopic_Impl *)
128 //========================================================================
130 BOOL SfxAppEvent_Impl( ApplicationEvent &rAppEvent,
131 const String &rCmd, const String &rEvent )
133 /* [Beschreibung]
135 Pr"uft, ob 'rCmd' das Event 'rEvent' ist (ohne '(') und baut
136 aus diesem dann ein <ApplicationEvent> zusammen, das per
137 <Application::AppEvent()> ausgef"uhrt werden kann. Ist 'rCmd' das
138 angegegeben Event 'rEvent', dann wird TRUE zur"uckgegeben, sonst FALSE.
141 [Beispiel]
143 rCmd = "Open(\"d:\doc\doc.sdw\")"
144 rEvent = "Open"
148 String aEvent( rEvent );
149 aEvent += '(';
150 if ( rCmd.CompareIgnoreCaseToAscii( aEvent, aEvent.Len() ) == COMPARE_EQUAL )
152 String aData( rCmd );
153 aData.Erase( 0, aEvent.Len() );
154 if ( aData.Len() > 2 )
156 // in das ApplicationEvent-Format wandeln
157 aData.Erase( aData.Len()-1, 1 );
158 for ( USHORT n = 0; n < aData.Len(); ++n )
160 if ( aData.GetChar(n) == 0x0022 ) // " = 22h
161 for ( ; aData.GetChar(++n) != 0x0022 ; )
162 /* empty loop */ ;
163 else if ( aData.GetChar(n) == 0x0020 ) // SPACE = 20h
164 aData.SetChar(n, '\n');
166 aData.EraseAllChars( 0x0022 );
167 ApplicationAddress aAddr;
168 rAppEvent = ApplicationEvent( String(), aAddr, U2S(rEvent), aData );
169 return TRUE;
173 return FALSE;
176 //-------------------------------------------------------------------------
178 long SfxApplication::DdeExecute
180 const String& rCmd // in unserer BASIC-Syntax formuliert
183 /* [Beschreibung]
185 Diese Methode kann vom Applikationsentwickler "uberladen werden,
186 um an seine SfxApplication-Subklasse gerichtete DDE-Kommandos
187 zu empfangen.
189 Die Basisimplementierung versteht die API-Funktionalit"at der
190 betreffenden SfxApplication-Subklasse in BASIC-Syntax. R"uckgabewerte
191 k"onnen dabei leider nicht "ubertragen werden.
195 // Print oder Open-Event?
196 ApplicationEvent aAppEvent;
197 if ( SfxAppEvent_Impl( aAppEvent, rCmd, DEFINE_CONST_UNICODE("Print") ) ||
198 SfxAppEvent_Impl( aAppEvent, rCmd, DEFINE_CONST_UNICODE("Open") ) )
199 GetpApp()->AppEvent( aAppEvent );
200 else
202 // alle anderen per BASIC
203 EnterBasicCall();
204 StarBASIC* pBasic = GetBasic();
205 DBG_ASSERT( pBasic, "Wo ist mein Basic???" );
206 SbxVariable* pRet = pBasic->Execute( rCmd );
207 LeaveBasicCall();
208 if( !pRet )
210 SbxBase::ResetError();
211 return 0;
214 return 1;
217 //--------------------------------------------------------------------
219 long SfxApplication::DdeGetData
221 const String&, // das anzusprechende Item
222 const String&, // in: Format
223 ::com::sun::star::uno::Any& // out: angeforderte Daten
226 /* [Beschreibung]
228 Diese Methode kann vom Applikationsentwickler "uberladen werden,
229 um an seine SfxApplication-Subklasse gerichtete DDE-Daten-Anforderungen
230 zu empfangen.
232 Die Basisimplementierung liefert keine Daten und gibt 0 zur"uck.
236 return 0;
239 //--------------------------------------------------------------------
241 long SfxApplication::DdeSetData
243 const String&, // das anzusprechende Item
244 const String&, // in: Format
245 const ::com::sun::star::uno::Any& // out: angeforderte Daten
248 /* [Beschreibung]
250 Diese Methode kann vom Applikationsentwickler "uberladen werden,
251 um an seine SfxApplication-Subklasse gerichtete DDE-Daten
252 zu empfangen.
254 Die Basisimplementierung nimmt keine Daten entgegen und liefert 0 zur"uck.
258 return 0;
261 //--------------------------------------------------------------------
263 ::sfx2::SvLinkSource* SfxApplication::DdeCreateLinkSource
265 const String& // das zu erzeugende Item
268 /* [Beschreibung]
270 Diese Methode kann vom Applikationsentwickler "uberladen werden,
271 um an seiner SfxApplication-Subklasse einen DDE-Hotlink einzurichten
273 Die Basisimplementierung erzeugt keinen und liefert 0 zur"uck.
277 return 0;
280 //========================================================================
282 long SfxObjectShell::DdeExecute
284 const String& rCmd // in unserer BASIC-Syntax formuliert
287 /* [Beschreibung]
289 Diese Methode kann vom Applikationsentwickler "uberladen werden,
290 um an seine SfxObjectShell-Subklasse gerichtete DDE-Kommandos
291 zu empfangen.
293 Die Basisimplementierung f"uhrt nichts aus und liefert 0 zur"uck.
297 StarBASIC* pBasic = GetBasic();
298 DBG_ASSERT( pBasic, "Wo ist mein Basic???" ) ;
299 SbxVariable* pRet = pBasic->Execute( rCmd );
300 if( !pRet )
302 SbxBase::ResetError();
303 return 0;
306 return 1;
309 //--------------------------------------------------------------------
311 long SfxObjectShell::DdeGetData
313 const String&, // das anzusprechende Item
314 const String&, // in: Format
315 ::com::sun::star::uno::Any& // out: angeforderte Daten
318 /* [Beschreibung]
320 Diese Methode kann vom Applikationsentwickler "uberladen werden,
321 um an seine SfxObjectShell-Subklasse gerichtete DDE-Daten-Anforderungen
322 zu empfangen.
324 Die Basisimplementierung liefert keine Daten und gibt 0 zur"uck.
328 return 0;
331 //--------------------------------------------------------------------
333 long SfxObjectShell::DdeSetData
335 const String&, // das anzusprechende Item
336 const String&, // in: Format
337 const ::com::sun::star::uno::Any& // out: angeforderte Daten
340 /* [Beschreibung]
342 Diese Methode kann vom Applikationsentwickler "uberladen werden,
343 um an seine SfxObjectShell-Subklasse gerichtete DDE-Daten
344 zu empfangen.
346 Die Basisimplementierung nimmt keine Daten entgegen und liefert 0 zur"uck.
350 return 0;
353 //--------------------------------------------------------------------
354 ::sfx2::SvLinkSource* SfxObjectShell::DdeCreateLinkSource
356 const String& // das zu erzeugende Item
359 /* [Beschreibung]
361 Diese Methode kann vom Applikationsentwickler "uberladen werden,
362 um an seiner SfxObjectShell-Subklasse einen DDE-Hotlink einzurichten
364 Die Basisimplementierung erzeugt keinen und liefert 0 zur"uck.
368 return 0;
371 //========================================================================
373 long SfxViewFrame::DdeExecute
375 const String& rCmd // in unserer BASIC-Syntax formuliert
378 /* [Beschreibung]
380 Diese Methode kann vom Applikationsentwickler "uberladen werden,
381 um an seine SfxViewFrame-Subklasse gerichtete DDE-Kommandos
382 zu empfangen.
384 Die Basisimplementierung versteht die API-Funktionalit"at des
385 betreffenden SfxViewFrame, der darin dargestellten SfxViewShell und
386 der betreffenden SfxObjectShell-Subklasse in BASIC-Syntax.
387 R"uckgabewerte k"onnen dabei leider nicht "ubertragen werden.
391 if ( GetObjectShell() )
392 return GetObjectShell()->DdeExecute( rCmd );
394 return 0;
397 //--------------------------------------------------------------------
399 long SfxViewFrame::DdeGetData
401 const String&, // das anzusprechende Item
402 const String&, // in: Format
403 ::com::sun::star::uno::Any& // out: angeforderte Daten
406 /* [Beschreibung]
408 Diese Methode kann vom Applikationsentwickler "uberladen werden,
409 um an seine SfxViewFrame-Subklasse gerichtete DDE-Daten-Anforderungen
410 zu empfangen.
412 Die Basisimplementierung liefert keine Daten und gibt 0 zur"uck.
416 return 0;
419 //--------------------------------------------------------------------
421 long SfxViewFrame::DdeSetData
423 const String& , // das anzusprechende Item
424 const String& , // in: Format
425 const ::com::sun::star::uno::Any& // out: angeforderte Daten
428 /* [Beschreibung]
430 Diese Methode kann vom Applikationsentwickler "uberladen werden,
431 um an seine SfxViewFrame-Subklasse gerichtete DDE-Daten
432 zu empfangen.
434 Die Basisimplementierung nimmt keine Daten entgegen und liefert 0 zur"uck.
438 return 0;
441 //--------------------------------------------------------------------
443 ::sfx2::SvLinkSource* SfxViewFrame::DdeCreateLinkSource
445 const String& // das zu erzeugende Item
448 /* [Beschreibung]
450 Diese Methode kann vom Applikationsentwickler "uberladen werden,
451 um an seiner SfxViewFrame-Subklasse einen DDE-Hotlink einzurichten
453 Die Basisimplementierung erzeugt keinen und liefert 0 zur"uck.
457 return 0;
460 //========================================================================
462 BOOL SfxApplication::InitializeDde()
464 DBG_ASSERT( !pAppData_Impl->pDdeService,
465 "Dde kann nicht mehrfach initialisiert werden" );
467 pAppData_Impl->pDdeService = new ImplDdeService( Application::GetAppName() );
468 int nError = pAppData_Impl->pDdeService->GetError();
469 if( !nError )
471 pAppData_Impl->pDocTopics = new SfxDdeDocTopics_Impl;
473 // wir wollen auf jedenfall RTF unterstuetzen!
474 pAppData_Impl->pDdeService->AddFormat( FORMAT_RTF );
476 // Config-Pfad als Topic wegen Mehrfachstart
477 INetURLObject aOfficeLockFile( SvtPathOptions().GetUserConfigPath() );
478 aOfficeLockFile.insertName( DEFINE_CONST_UNICODE( "soffice.lck" ) );
479 String aService( SfxDdeServiceName_Impl(
480 aOfficeLockFile.GetMainURL(INetURLObject::DECODE_TO_IURI) ) );
481 aService.ToUpperAscii();
482 pAppData_Impl->pDdeService2 = new ImplDdeService( aService );
483 pAppData_Impl->pTriggerTopic = new SfxDdeTriggerTopic_Impl;
484 pAppData_Impl->pDdeService2->AddTopic( *pAppData_Impl->pTriggerTopic );
486 return !nError;
489 void SfxAppData_Impl::DeInitDDE()
491 DELETEZ( pTriggerTopic );
492 DELETEZ( pDdeService2 );
493 DELETEZ( pDocTopics );
494 DELETEZ( pDdeService );
497 //--------------------------------------------------------------------
499 void SfxApplication::AddDdeTopic( SfxObjectShell* pSh )
501 DBG_ASSERT( pAppData_Impl->pDocTopics, "es gibt gar keinen Dde-Service" );
502 //OV: Im Serverbetrieb ist DDE abgeklemmt!
503 if( !pAppData_Impl->pDocTopics )
504 return;
506 // doppeltes Eintragen verhindern
507 String sShellNm;
508 BOOL bFnd = FALSE;
509 for( USHORT n = pAppData_Impl->pDocTopics->Count(); n; )
510 if( (*pAppData_Impl->pDocTopics)[ --n ]->pSh == pSh )
512 // JP 18.03.96 - Bug 26470
513 // falls das Document unbenannt wurde, ist trotzdem ein
514 // neues Topics anzulegen!
515 if( !bFnd )
517 bFnd = TRUE;
518 (sShellNm = pSh->GetTitle(SFX_TITLE_FULLNAME)).ToLowerAscii();
520 String sNm( (*pAppData_Impl->pDocTopics)[ n ]->GetName() );
521 if( sShellNm == sNm.ToLowerAscii() )
522 return ;
525 const SfxDdeDocTopic_Impl* pTopic = new SfxDdeDocTopic_Impl( pSh );
526 pAppData_Impl->pDocTopics->Insert( pTopic,
527 pAppData_Impl->pDocTopics->Count() );
528 pAppData_Impl->pDdeService->AddTopic( *pTopic );
531 void SfxApplication::RemoveDdeTopic( SfxObjectShell* pSh )
533 DBG_ASSERT( pAppData_Impl->pDocTopics, "es gibt gar keinen Dde-Service" );
534 //OV: Im Serverbetrieb ist DDE abgeklemmt!
535 if( !pAppData_Impl->pDocTopics )
536 return;
538 SfxDdeDocTopic_Impl* pTopic;
539 for( USHORT n = pAppData_Impl->pDocTopics->Count(); n; )
540 if( ( pTopic = (*pAppData_Impl->pDocTopics)[ --n ])->pSh == pSh )
542 pAppData_Impl->pDdeService->RemoveTopic( *pTopic );
543 pAppData_Impl->pDocTopics->DeleteAndDestroy( n );
547 const DdeService* SfxApplication::GetDdeService() const
549 return pAppData_Impl->pDdeService;
552 DdeService* SfxApplication::GetDdeService()
554 return pAppData_Impl->pDdeService;
557 //--------------------------------------------------------------------
559 BOOL ImplDdeService::MakeTopic( const String& rNm )
561 // Workaround gegen Event nach unserem Main() unter OS/2
562 // passierte wenn man beim Beenden aus dem OffMgr die App neu startet
563 if ( !Application::IsInExecute() )
564 return FALSE;
566 // das Topic rNm wird gesucht, haben wir es ?
567 // erstmal nur ueber die ObjectShells laufen und die mit dem
568 // Namen heraussuchen:
569 BOOL bRet = FALSE;
570 String sNm( rNm );
571 sNm.ToLowerAscii();
572 TypeId aType( TYPE(SfxObjectShell) );
573 SfxObjectShell* pShell = SfxObjectShell::GetFirst( &aType );
574 while( pShell )
576 String sTmp( pShell->GetTitle(SFX_TITLE_FULLNAME) );
577 sTmp.ToLowerAscii();
578 if( sTmp == sNm ) // die wollen wir haben
580 SFX_APP()->AddDdeTopic( pShell );
581 bRet = TRUE;
582 break;
584 pShell = SfxObjectShell::GetNext( *pShell, &aType );
587 if( !bRet )
589 INetURLObject aWorkPath( SvtPathOptions().GetWorkPath() );
590 INetURLObject aFile;
591 if ( aWorkPath.GetNewAbsURL( rNm, &aFile ) &&
592 SfxContentHelper::IsDocument( aFile.GetMainURL( INetURLObject::NO_DECODE ) ) )
594 // File vorhanden
596 // dann versuche die Datei zu laden:
597 SfxStringItem aName( SID_FILE_NAME, aFile.GetMainURL( INetURLObject::NO_DECODE ) );
598 SfxBoolItem aNewView(SID_OPEN_NEW_VIEW, TRUE);
599 // SfxBoolItem aHidden(SID_HIDDEN, TRUE);
600 // minimiert!
601 SfxUInt16Item aViewStat( SID_VIEW_ZOOM_MODE, 0 );
602 SfxRectangleItem aRectItem( SID_VIEW_POS_SIZE, Rectangle() );
604 SfxBoolItem aSilent(SID_SILENT, TRUE);
605 SfxDispatcher* pDispatcher = SFX_APP()->GetDispatcher_Impl();
606 const SfxPoolItem* pRet = pDispatcher->Execute( SID_OPENDOC,
607 SFX_CALLMODE_SYNCHRON,
608 &aName, &aNewView,
609 &aViewStat,&aRectItem/*aHidden*/,
610 &aSilent, 0L );
612 if( pRet && pRet->ISA( SfxViewFrameItem ) &&
613 ((SfxViewFrameItem*)pRet)->GetFrame() &&
614 0 != ( pShell = ((SfxViewFrameItem*)pRet)
615 ->GetFrame()->GetObjectShell() ) )
617 SFX_APP()->AddDdeTopic( pShell );
618 bRet = TRUE;
622 return bRet;
625 String ImplDdeService::Topics()
627 String sRet;
628 if( GetSysTopic() )
629 sRet += GetSysTopic()->GetName();
631 TypeId aType( TYPE(SfxObjectShell) );
632 SfxObjectShell* pShell = SfxObjectShell::GetFirst( &aType );
633 while( pShell )
635 if( SfxViewFrame::GetFirst( pShell, TYPE(SfxTopViewFrame) ))
637 if( sRet.Len() )
638 sRet += '\t';
639 sRet += pShell->GetTitle(SFX_TITLE_FULLNAME);
641 pShell = SfxObjectShell::GetNext( *pShell, &aType );
643 if( sRet.Len() )
644 sRet += DEFINE_CONST_UNICODE("\r\n");
645 return sRet;
648 BOOL ImplDdeService::SysTopicExecute( const String* pStr )
650 return (BOOL)SFX_APP()->DdeExecute( *pStr );
653 //--------------------------------------------------------------------
655 BOOL SfxDdeTriggerTopic_Impl::Execute( const String* )
657 return TRUE;
660 //--------------------------------------------------------------------
661 DdeData* SfxDdeDocTopic_Impl::Get( ULONG nFormat )
663 String sMimeType( SotExchange::GetFormatMimeType( nFormat ));
664 ::com::sun::star::uno::Any aValue;
665 long nRet = pSh->DdeGetData( GetCurItem(), sMimeType, aValue );
666 if( nRet && aValue.hasValue() && ( aValue >>= aSeq ) )
668 aData = DdeData( aSeq.getConstArray(), aSeq.getLength(), nFormat );
669 return &aData;
671 aSeq.realloc( 0 );
672 return 0;
675 BOOL SfxDdeDocTopic_Impl::Put( const DdeData* pData )
677 aSeq = ::com::sun::star::uno::Sequence< sal_Int8 >(
678 (sal_Int8*)(const void*)*pData, (long)*pData );
679 BOOL bRet;
680 if( aSeq.getLength() )
682 ::com::sun::star::uno::Any aValue;
683 aValue <<= aSeq;
684 String sMimeType( SotExchange::GetFormatMimeType( pData->GetFormat() ));
685 bRet = 0 != pSh->DdeSetData( GetCurItem(), sMimeType, aValue );
687 else
688 bRet = FALSE;
689 return bRet;
692 BOOL SfxDdeDocTopic_Impl::Execute( const String* pStr )
694 long nRet = pStr ? pSh->DdeExecute( *pStr ) : 0;
695 return 0 != nRet;
698 BOOL SfxDdeDocTopic_Impl::MakeItem( const String& rItem )
700 AddItem( DdeItem( rItem ) );
701 return TRUE;
704 BOOL SfxDdeDocTopic_Impl::StartAdviseLoop()
706 BOOL bRet = FALSE;
707 ::sfx2::SvLinkSource* pNewObj = pSh->DdeCreateLinkSource( GetCurItem() );
708 if( pNewObj )
710 // dann richten wir auch einen entsprechenden SvBaseLink ein
711 String sNm, sTmp( Application::GetAppName() );
712 ::sfx2::MakeLnkName( sNm, &sTmp, pSh->GetTitle(SFX_TITLE_FULLNAME), GetCurItem() );
713 new ::sfx2::SvBaseLink( sNm, OBJECT_DDE_EXTERN, pNewObj );
714 bRet = TRUE;
716 return bRet;