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: 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>
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>
57 #include <sfx2/docfile.hxx>
59 //========================================================================
61 String
SfxDdeServiceName_Impl( const String
& sIn
)
63 ByteString sTemp
= U2S( sIn
);
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
77 ImplDdeService( const String
& 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
93 SfxDdeTriggerTopic_Impl()
94 : DdeTopic( DEFINE_CONST_UNICODE("TRIGGER") )
97 virtual BOOL
Execute( const String
* );
100 class SfxDdeDocTopic_Impl
: public DdeTopic
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
);
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
)
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.
143 rCmd = "Open(\"d:\doc\doc.sdw\")"
148 String
aEvent( rEvent
);
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 ; )
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
);
176 //-------------------------------------------------------------------------
178 long SfxApplication::DdeExecute
180 const String
& rCmd
// in unserer BASIC-Syntax formuliert
185 Diese Methode kann vom Applikationsentwickler "uberladen werden,
186 um an seine SfxApplication-Subklasse gerichtete DDE-Kommandos
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
);
202 // alle anderen per BASIC
204 StarBASIC
* pBasic
= GetBasic();
205 DBG_ASSERT( pBasic
, "Wo ist mein Basic???" );
206 SbxVariable
* pRet
= pBasic
->Execute( rCmd
);
210 SbxBase::ResetError();
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
228 Diese Methode kann vom Applikationsentwickler "uberladen werden,
229 um an seine SfxApplication-Subklasse gerichtete DDE-Daten-Anforderungen
232 Die Basisimplementierung liefert keine Daten und gibt 0 zur"uck.
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
250 Diese Methode kann vom Applikationsentwickler "uberladen werden,
251 um an seine SfxApplication-Subklasse gerichtete DDE-Daten
254 Die Basisimplementierung nimmt keine Daten entgegen und liefert 0 zur"uck.
261 //--------------------------------------------------------------------
263 ::sfx2::SvLinkSource
* SfxApplication::DdeCreateLinkSource
265 const String
& // das zu erzeugende Item
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.
280 //========================================================================
282 long SfxObjectShell::DdeExecute
284 const String
& rCmd
// in unserer BASIC-Syntax formuliert
289 Diese Methode kann vom Applikationsentwickler "uberladen werden,
290 um an seine SfxObjectShell-Subklasse gerichtete DDE-Kommandos
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
);
302 SbxBase::ResetError();
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
320 Diese Methode kann vom Applikationsentwickler "uberladen werden,
321 um an seine SfxObjectShell-Subklasse gerichtete DDE-Daten-Anforderungen
324 Die Basisimplementierung liefert keine Daten und gibt 0 zur"uck.
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
342 Diese Methode kann vom Applikationsentwickler "uberladen werden,
343 um an seine SfxObjectShell-Subklasse gerichtete DDE-Daten
346 Die Basisimplementierung nimmt keine Daten entgegen und liefert 0 zur"uck.
353 //--------------------------------------------------------------------
354 ::sfx2::SvLinkSource
* SfxObjectShell::DdeCreateLinkSource
356 const String
& // das zu erzeugende Item
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.
371 //========================================================================
373 long SfxViewFrame::DdeExecute
375 const String
& rCmd
// in unserer BASIC-Syntax formuliert
380 Diese Methode kann vom Applikationsentwickler "uberladen werden,
381 um an seine SfxViewFrame-Subklasse gerichtete DDE-Kommandos
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
);
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
408 Diese Methode kann vom Applikationsentwickler "uberladen werden,
409 um an seine SfxViewFrame-Subklasse gerichtete DDE-Daten-Anforderungen
412 Die Basisimplementierung liefert keine Daten und gibt 0 zur"uck.
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
430 Diese Methode kann vom Applikationsentwickler "uberladen werden,
431 um an seine SfxViewFrame-Subklasse gerichtete DDE-Daten
434 Die Basisimplementierung nimmt keine Daten entgegen und liefert 0 zur"uck.
441 //--------------------------------------------------------------------
443 ::sfx2::SvLinkSource
* SfxViewFrame::DdeCreateLinkSource
445 const String
& // das zu erzeugende Item
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.
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();
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
);
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
)
506 // doppeltes Eintragen verhindern
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!
518 (sShellNm
= pSh
->GetTitle(SFX_TITLE_FULLNAME
)).ToLowerAscii();
520 String
sNm( (*pAppData_Impl
->pDocTopics
)[ n
]->GetName() );
521 if( sShellNm
== sNm
.ToLowerAscii() )
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
)
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() )
566 // das Topic rNm wird gesucht, haben wir es ?
567 // erstmal nur ueber die ObjectShells laufen und die mit dem
568 // Namen heraussuchen:
572 TypeId
aType( TYPE(SfxObjectShell
) );
573 SfxObjectShell
* pShell
= SfxObjectShell::GetFirst( &aType
);
576 String
sTmp( pShell
->GetTitle(SFX_TITLE_FULLNAME
) );
578 if( sTmp
== sNm
) // die wollen wir haben
580 SFX_APP()->AddDdeTopic( pShell
);
584 pShell
= SfxObjectShell::GetNext( *pShell
, &aType
);
589 INetURLObject
aWorkPath( SvtPathOptions().GetWorkPath() );
591 if ( aWorkPath
.GetNewAbsURL( rNm
, &aFile
) &&
592 SfxContentHelper::IsDocument( aFile
.GetMainURL( INetURLObject::NO_DECODE
) ) )
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);
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
,
609 &aViewStat
,&aRectItem
/*aHidden*/,
612 if( pRet
&& pRet
->ISA( SfxViewFrameItem
) &&
613 ((SfxViewFrameItem
*)pRet
)->GetFrame() &&
614 0 != ( pShell
= ((SfxViewFrameItem
*)pRet
)
615 ->GetFrame()->GetObjectShell() ) )
617 SFX_APP()->AddDdeTopic( pShell
);
625 String
ImplDdeService::Topics()
629 sRet
+= GetSysTopic()->GetName();
631 TypeId
aType( TYPE(SfxObjectShell
) );
632 SfxObjectShell
* pShell
= SfxObjectShell::GetFirst( &aType
);
635 if( SfxViewFrame::GetFirst( pShell
, TYPE(SfxTopViewFrame
) ))
639 sRet
+= pShell
->GetTitle(SFX_TITLE_FULLNAME
);
641 pShell
= SfxObjectShell::GetNext( *pShell
, &aType
);
644 sRet
+= DEFINE_CONST_UNICODE("\r\n");
648 BOOL
ImplDdeService::SysTopicExecute( const String
* pStr
)
650 return (BOOL
)SFX_APP()->DdeExecute( *pStr
);
653 //--------------------------------------------------------------------
655 BOOL
SfxDdeTriggerTopic_Impl::Execute( const String
* )
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
);
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
);
680 if( aSeq
.getLength() )
682 ::com::sun::star::uno::Any aValue
;
684 String
sMimeType( SotExchange::GetFormatMimeType( pData
->GetFormat() ));
685 bRet
= 0 != pSh
->DdeSetData( GetCurItem(), sMimeType
, aValue
);
692 BOOL
SfxDdeDocTopic_Impl::Execute( const String
* pStr
)
694 long nRet
= pStr
? pSh
->DdeExecute( *pStr
) : 0;
698 BOOL
SfxDdeDocTopic_Impl::MakeItem( const String
& rItem
)
700 AddItem( DdeItem( rItem
) );
704 BOOL
SfxDdeDocTopic_Impl::StartAdviseLoop()
707 ::sfx2::SvLinkSource
* pNewObj
= pSh
->DdeCreateLinkSource( GetCurItem() );
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
);