1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include <sot/exchange.hxx>
21 #include <sfx2/linkmgr.hxx>
22 #include <com/sun/star/uno/Sequence.h>
24 #include <IDocumentLinksAdministration.hxx>
25 #include <IDocumentLayoutAccess.hxx>
27 #include <swbaslnk.hxx>
30 #include <bookmark.hxx>
32 #include <shellio.hxx>
34 using namespace ::com::sun::star
;
36 SwServerObject::~SwServerObject()
40 bool SwServerObject::GetData( uno::Any
& rData
,
41 const OUString
& rMimeType
, bool )
45 switch( SotExchange::GetFormatIdFromMimeType( rMimeType
) )
47 case SotClipboardFormatId::STRING
:
48 ::GetASCWriter( std::u16string_view(), OUString(), xWrt
);
51 case SotClipboardFormatId::RTF
:
52 case SotClipboardFormatId::RICHTEXT
:
53 // mba: no BaseURL for data exchange
54 ::GetRTFWriter( std::u16string_view(), OUString(), xWrt
);
61 SwPaM
* pPam
= nullptr;
65 if( m_CNTNT_TYPE
.pBkmk
->IsExpanded() )
68 pPam
= new SwPaM( m_CNTNT_TYPE
.pBkmk
->GetMarkPos(),
69 m_CNTNT_TYPE
.pBkmk
->GetOtherMarkPos() );
74 pPam
= new SwPaM( *m_CNTNT_TYPE
.pTableNd
,
75 *m_CNTNT_TYPE
.pTableNd
->EndOfSectionNode() );
79 pPam
= new SwPaM( SwPosition( *m_CNTNT_TYPE
.pSectNd
) );
80 pPam
->Move( fnMoveForward
);
82 pPam
->GetPoint()->Assign( *m_CNTNT_TYPE
.pSectNd
->EndOfSectionNode() );
83 pPam
->Move( fnMoveBackward
);
85 case NONE_SERVER
: break;
91 SvMemoryStream
aMemStm( 65535, 65535 );
92 SwWriter
aWrt( aMemStm
, *pPam
, false );
93 if( !aWrt
.Write( xWrt
).IsError() )
95 aMemStm
.WriteChar( '\0' ); // append a zero char
96 rData
<<= uno::Sequence
< sal_Int8
>(
97 static_cast<sal_Int8
const *>(aMemStm
.GetData()),
107 void SwServerObject::SendDataChanged( const SwPosition
& rPos
)
109 // Is someone interested in our changes?
110 if( !HasDataLinks() )
114 const SwStartNode
* pNd
= nullptr;
117 case BOOKMARK_SERVER
:
118 if( m_CNTNT_TYPE
.pBkmk
->IsExpanded() )
120 bCall
= m_CNTNT_TYPE
.pBkmk
->GetMarkStart() <= rPos
121 && rPos
< m_CNTNT_TYPE
.pBkmk
->GetMarkEnd();
125 case TABLE_SERVER
: pNd
= m_CNTNT_TYPE
.pTableNd
; break;
126 case SECTION_SERVER
: pNd
= m_CNTNT_TYPE
.pSectNd
; break;
127 case NONE_SERVER
: break;
131 SwNodeOffset nNd
= rPos
.GetNodeIndex();
132 bCall
= pNd
->GetIndex() < nNd
&& nNd
< pNd
->EndOfSectionIndex();
137 // Recognize recursions and flag them
138 IsLinkInServer( nullptr );
139 SvLinkSource::NotifyDataChanged();
143 void SwServerObject::SendDataChanged( const SwPaM
& rRange
)
145 // Is someone interested in our changes?
146 if( !HasDataLinks() )
150 const SwStartNode
* pNd
= nullptr;
151 auto [pStt
, pEnd
] = rRange
.StartEnd(); // SwPosition*
154 case BOOKMARK_SERVER
:
155 if(m_CNTNT_TYPE
.pBkmk
->IsExpanded())
157 bCall
= *pStt
<= m_CNTNT_TYPE
.pBkmk
->GetMarkEnd()
158 && *pEnd
> m_CNTNT_TYPE
.pBkmk
->GetMarkStart();
162 case TABLE_SERVER
: pNd
= m_CNTNT_TYPE
.pTableNd
; break;
163 case SECTION_SERVER
: pNd
= m_CNTNT_TYPE
.pSectNd
; break;
164 case NONE_SERVER
: break;
168 // Is the start area within the node area?
169 bCall
= pStt
->GetNodeIndex() < pNd
->EndOfSectionIndex() &&
170 pEnd
->GetNodeIndex() >= pNd
->GetIndex();
175 // Recognize recursions and flag them
176 IsLinkInServer( nullptr );
177 SvLinkSource::NotifyDataChanged();
181 bool SwServerObject::IsLinkInServer( const SwBaseLink
* pChkLnk
) const
183 SwNodeOffset
nSttNd(0), nEndNd(0);
184 const SwNode
* pNd
= nullptr;
185 const SwNodes
* pNds
= nullptr;
189 case BOOKMARK_SERVER
:
190 if( m_CNTNT_TYPE
.pBkmk
->IsExpanded() )
192 const SwPosition
* pStt
= &m_CNTNT_TYPE
.pBkmk
->GetMarkStart(),
193 * pEnd
= &m_CNTNT_TYPE
.pBkmk
->GetMarkEnd();
195 nSttNd
= pStt
->GetNodeIndex();
196 nEndNd
= pEnd
->GetNodeIndex();
197 pNds
= &pStt
->GetNodes();
201 case TABLE_SERVER
: pNd
= m_CNTNT_TYPE
.pTableNd
; break;
202 case SECTION_SERVER
: pNd
= m_CNTNT_TYPE
.pSectNd
; break;
204 case SECTION_SERVER
+1:
210 nSttNd
= pNd
->GetIndex();
211 nEndNd
= pNd
->EndOfSectionIndex();
212 pNds
= &pNd
->GetNodes();
215 if( nSttNd
&& nEndNd
)
218 const ::sfx2::SvBaseLinks
& rLnks
= pNds
->GetDoc().getIDocumentLinksAdministration().GetLinkManager().GetLinks();
220 // To avoid recursions: convert ServerType!
221 SwServerObject::ServerModes eSave
= m_eType
;
223 const_cast<SwServerObject
*>(this)->m_eType
= NONE_SERVER
;
224 for( size_t n
= rLnks
.size(); n
; )
226 const ::sfx2::SvBaseLink
* pLnk
= &(*rLnks
[ --n
]);
227 if (sfx2::SvBaseLinkObjectType::ClientGraphic
!= pLnk
->GetObjType() &&
228 dynamic_cast<const SwBaseLink
*>( pLnk
) != nullptr &&
229 !static_cast<const SwBaseLink
*>(pLnk
)->IsNoDataFlag() &&
230 static_cast<const SwBaseLink
*>(pLnk
)->IsInRange( nSttNd
, nEndNd
))
234 if( pLnk
== pChkLnk
||
235 static_cast<const SwBaseLink
*>(pLnk
)->IsRecursion( pChkLnk
) )
238 else if( static_cast<const SwBaseLink
*>(pLnk
)->IsRecursion( static_cast<const SwBaseLink
*>(pLnk
) ) )
239 const_cast<SwBaseLink
*>(static_cast<const SwBaseLink
*>(pLnk
))->SetNoDataFlag();
243 const_cast<SwServerObject
*>(this)->m_eType
= eSave
;
249 void SwServerObject::SetNoServer()
251 if(m_eType
== BOOKMARK_SERVER
&& m_CNTNT_TYPE
.pBkmk
)
253 ::sw::mark::DdeBookmark
* const pDdeBookmark
= dynamic_cast< ::sw::mark::DdeBookmark
* >(m_CNTNT_TYPE
.pBkmk
);
256 m_CNTNT_TYPE
.pBkmk
= nullptr;
257 m_eType
= NONE_SERVER
;
258 pDdeBookmark
->SetRefObject(nullptr);
263 void SwServerObject::SetDdeBookmark( ::sw::mark::IMark
& rBookmark
)
265 ::sw::mark::DdeBookmark
* const pDdeBookmark
= dynamic_cast< ::sw::mark::DdeBookmark
* >(&rBookmark
);
268 m_eType
= BOOKMARK_SERVER
;
269 m_CNTNT_TYPE
.pBkmk
= &rBookmark
;
270 pDdeBookmark
->SetRefObject(this);
273 OSL_FAIL("SwServerObject::SetNoServer(..)"
274 " - setting a bookmark that is not DDE-capable");
277 SwDataChanged::SwDataChanged( const SwPaM
& rPam
)
278 : m_pPam( &rPam
), m_pPos( nullptr ), m_rDoc( rPam
.GetDoc() )
280 m_nContent
= rPam
.GetPoint()->GetContentIndex();
283 SwDataChanged::SwDataChanged( SwDoc
& rDc
, const SwPosition
& rPos
)
284 : m_pPam( nullptr ), m_pPos( &rPos
), m_rDoc( rDc
)
286 m_nContent
= rPos
.GetContentIndex();
289 SwDataChanged::~SwDataChanged()
291 // JP 09.04.96: Only if the Layout is available (thus during input)
292 if( !m_rDoc
.getIDocumentLayoutAccess().GetCurrentViewShell() )
295 const ::sfx2::SvLinkSources
& rServers
= m_rDoc
.getIDocumentLinksAdministration().GetLinkManager().GetServers();
297 ::sfx2::SvLinkSources
aTemp(rServers
);
298 for( const auto& rpLinkSrc
: aTemp
)
300 ::sfx2::SvLinkSourceRef
refObj( rpLinkSrc
);
301 // Anyone else interested in the Object?
302 if( refObj
->HasDataLinks())
303 if (auto pServerObj
= dynamic_cast<SwServerObject
*>( refObj
.get() ))
306 pServerObj
->SendDataChanged( *m_pPos
);
308 pServerObj
->SendDataChanged( *m_pPam
);
311 // We shouldn't have a connection anymore
312 if( !refObj
->HasDataLinks() )
314 // Then remove from the list
315 m_rDoc
.getIDocumentLinksAdministration().GetLinkManager().RemoveServer( rpLinkSrc
);
320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */