xref: /trunk/main/sw/source/core/doc/swserv.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #include <sot/storage.hxx>
33 #include <sfx2/linkmgr.hxx>
34 #include <com/sun/star/uno/Sequence.h>
35 #include <doc.hxx>
36 #include <swtypes.hxx>
37 #include <swserv.hxx>
38 #include <swbaslnk.hxx>
39 #include <mvsave.hxx>
40 #include <IMark.hxx>
41 #include <bookmrk.hxx>
42 #include <pam.hxx>
43 #include <shellio.hxx>
44 #ifndef _SWERROR_H
45 #include <swerror.h>
46 #endif
47 
48 using namespace ::com::sun::star;
49 
50 SV_IMPL_REF( SwServerObject )
51 
52 SwServerObject::~SwServerObject()
53 {
54 }
55 
56 
57 sal_Bool SwServerObject::GetData( uno::Any & rData,
58                                 const String & rMimeType, sal_Bool )
59 {
60     sal_Bool bRet = sal_False;
61     WriterRef xWrt;
62     switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
63     {
64     case FORMAT_STRING:
65         ::GetASCWriter( aEmptyStr, String(), xWrt );
66         break;
67 
68     case FORMAT_RTF:
69         // mba: no BaseURL for data exchange
70         ::GetRTFWriter( aEmptyStr, String(), xWrt );
71         break;
72     }
73 
74     if( xWrt.Is() )
75     {
76         SwPaM* pPam = 0;
77         switch( eType )
78         {
79         case BOOKMARK_SERVER:
80             if( CNTNT_TYPE.pBkmk->IsExpanded() )
81             {
82                 // Bereich aufspannen
83                 pPam = new SwPaM( CNTNT_TYPE.pBkmk->GetMarkPos(),
84                                 CNTNT_TYPE.pBkmk->GetOtherMarkPos() );
85             }
86             break;
87 
88         case TABLE_SERVER:
89             pPam = new SwPaM( *CNTNT_TYPE.pTblNd,
90                             *CNTNT_TYPE.pTblNd->EndOfSectionNode() );
91             break;
92 
93         case SECTION_SERVER:
94             pPam = new SwPaM( SwPosition( *CNTNT_TYPE.pSectNd ) );
95             pPam->Move( fnMoveForward );
96             pPam->SetMark();
97             pPam->GetPoint()->nNode = *CNTNT_TYPE.pSectNd->EndOfSectionNode();
98             pPam->Move( fnMoveBackward );
99             break;
100         case NONE_SERVER: break;
101         }
102 
103         if( pPam )
104         {
105             // Stream anlegen
106             SvMemoryStream aMemStm( 65535, 65535 );
107             SwWriter aWrt( aMemStm, *pPam, sal_False );
108             if( !IsError( aWrt.Write( xWrt )) )
109             {
110                 aMemStm << '\0';        // append a zero char
111                 rData <<= uno::Sequence< sal_Int8 >(
112                                         (sal_Int8*)aMemStm.GetData(),
113                                         aMemStm.Seek( STREAM_SEEK_TO_END ) );
114                 bRet = sal_True;
115             }
116 
117             delete pPam;
118         }
119     }
120     return bRet;
121 }
122 
123 
124 sal_Bool SwServerObject::SetData( const String & ,
125                     const uno::Any& )
126 {
127     // set new data into the "server" -> at first nothing to do
128     return sal_False;
129 }
130 
131 
132 void SwServerObject::SendDataChanged( const SwPosition& rPos )
133 {
134     // ist an unseren Aenderungen jemand interessiert ?
135     if( HasDataLinks() )
136     {
137         int bCall = sal_False;
138         const SwStartNode* pNd = 0;
139         switch( eType )
140         {
141             case BOOKMARK_SERVER:
142                 if( CNTNT_TYPE.pBkmk->IsExpanded() )
143                 {
144                     bCall = CNTNT_TYPE.pBkmk->GetMarkStart() <= rPos
145                         && rPos < CNTNT_TYPE.pBkmk->GetMarkEnd();
146                 }
147                 break;
148 
149             case TABLE_SERVER:      pNd = CNTNT_TYPE.pTblNd;    break;
150             case SECTION_SERVER:    pNd = CNTNT_TYPE.pSectNd;   break;
151             case NONE_SERVER: break;
152         }
153         if( pNd )
154         {
155             sal_uLong nNd = rPos.nNode.GetIndex();
156             bCall = pNd->GetIndex() < nNd && nNd < pNd->EndOfSectionIndex();
157         }
158 
159         if( bCall )
160         {
161             // Recursionen erkennen und flaggen
162             IsLinkInServer( 0 );
163             SvLinkSource::NotifyDataChanged();
164         }
165     }
166     // sonst melden wir uns ab !!
167 // ????? JP 27.06.95: geht das so ????
168 //  else
169 //      Closed();
170 }
171 
172 
173 void SwServerObject::SendDataChanged( const SwPaM& rRange )
174 {
175     // ist an unseren Aenderungen jemand interessiert ?
176     if( HasDataLinks() )
177     {
178         int bCall = sal_False;
179         const SwStartNode* pNd = 0;
180         const SwPosition* pStt = rRange.Start(), *pEnd = rRange.End();
181         switch( eType )
182         {
183         case BOOKMARK_SERVER:
184             if(CNTNT_TYPE.pBkmk->IsExpanded())
185             {
186                 bCall = *pStt <= CNTNT_TYPE.pBkmk->GetMarkEnd()
187                     && *pEnd > CNTNT_TYPE.pBkmk->GetMarkStart();
188             }
189             break;
190 
191         case TABLE_SERVER:      pNd = CNTNT_TYPE.pTblNd;    break;
192         case SECTION_SERVER:    pNd = CNTNT_TYPE.pSectNd;   break;
193         case NONE_SERVER: break;
194         }
195         if( pNd )
196         {
197             // liegt der Start-Bereich im Node Bereich ?
198             bCall = pStt->nNode.GetIndex() <  pNd->EndOfSectionIndex() &&
199                     pEnd->nNode.GetIndex() >= pNd->GetIndex();
200         }
201 
202         if( bCall )
203         {
204             // Recursionen erkennen und flaggen
205             IsLinkInServer( 0 );
206             SvLinkSource::NotifyDataChanged();
207         }
208     }
209     // sonst melden wir uns ab !!
210 // ????? JP 27.06.95: geht das so ????
211 //  else
212 //      Closed();
213 }
214 
215 
216 sal_Bool SwServerObject::IsLinkInServer( const SwBaseLink* pChkLnk ) const
217 {
218     sal_uLong nSttNd = 0, nEndNd = 0;
219     xub_StrLen nStt = 0;
220     xub_StrLen nEnd = 0;
221     const SwNode* pNd = 0;
222     const SwNodes* pNds = 0;
223 
224     switch( eType )
225     {
226     case BOOKMARK_SERVER:
227         if( CNTNT_TYPE.pBkmk->IsExpanded() )
228         {
229             const SwPosition* pStt = &CNTNT_TYPE.pBkmk->GetMarkStart(),
230                             * pEnd = &CNTNT_TYPE.pBkmk->GetMarkEnd();
231 
232             nSttNd = pStt->nNode.GetIndex();
233             nStt = pStt->nContent.GetIndex();
234             nEndNd = pEnd->nNode.GetIndex();
235             nEnd = pEnd->nContent.GetIndex();
236             pNds = &pStt->nNode.GetNodes();
237         }
238         break;
239 
240     case TABLE_SERVER:      pNd = CNTNT_TYPE.pTblNd;    break;
241     case SECTION_SERVER:    pNd = CNTNT_TYPE.pSectNd;   break;
242 
243     case SECTION_SERVER+1:
244         return sal_True;
245     }
246 
247     if( pNd )
248     {
249         nSttNd = pNd->GetIndex();
250         nEndNd = pNd->EndOfSectionIndex();
251         nStt = 0, nEnd = USHRT_MAX;
252         pNds = &pNd->GetNodes();
253     }
254 
255     if( nSttNd && nEndNd )
256     {
257         // LinkManager besorgen:
258         const ::sfx2::SvBaseLinks& rLnks = pNds->GetDoc()->GetLinkManager().GetLinks();
259 
260 // um Rekursionen zu Verhindern: ServerType umsetzen!
261 SwServerObject::ServerModes eSave = eType;
262 if( !pChkLnk )
263 // sowas sollte man nicht tun, wer weiss schon, wie gross ein enum ist
264 // ICC nimmt keinen int
265 // #41723#
266 //  *((int*)&eType) = SECTION_SERVER+1;
267     ((SwServerObject*)this)->eType = NONE_SERVER;
268         for( sal_uInt16 n = rLnks.Count(); n; )
269         {
270             const ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
271             if( pLnk && OBJECT_CLIENT_GRF != pLnk->GetObjType() &&
272                 pLnk->ISA( SwBaseLink ) &&
273                 !((SwBaseLink*)pLnk)->IsNoDataFlag() &&
274                 ((SwBaseLink*)pLnk)->IsInRange( nSttNd, nEndNd, nStt, nEnd ))
275             {
276                 if( pChkLnk )
277                 {
278                     if( pLnk == pChkLnk ||
279                         ((SwBaseLink*)pLnk)->IsRecursion( pChkLnk ) )
280                         return sal_True;
281                 }
282                 else if( ((SwBaseLink*)pLnk)->IsRecursion( (SwBaseLink*)pLnk ) )
283                     ((SwBaseLink*)pLnk)->SetNoDataFlag();
284             }
285         }
286 if( !pChkLnk )
287     //  *((int*)&eType) = eSave;
288     ((SwServerObject*)this)->eType = eSave;
289     }
290 
291     return sal_False;
292 }
293 
294 void SwServerObject::SetNoServer()
295 {
296     if(eType == BOOKMARK_SERVER && CNTNT_TYPE.pBkmk)
297     {
298         ::sw::mark::DdeBookmark* const pDdeBookmark = dynamic_cast< ::sw::mark::DdeBookmark* >(CNTNT_TYPE.pBkmk);
299         if(pDdeBookmark)
300 		{
301             CNTNT_TYPE.pBkmk = 0, eType = NONE_SERVER;
302 			pDdeBookmark->SetRefObject(NULL);
303 		}
304     }
305 }
306 
307 void SwServerObject::SetDdeBookmark( ::sw::mark::IMark& rBookmark)
308 {
309     ::sw::mark::DdeBookmark* const pDdeBookmark = dynamic_cast< ::sw::mark::DdeBookmark* >(&rBookmark);
310     if(pDdeBookmark)
311     {
312         eType = BOOKMARK_SERVER;
313         CNTNT_TYPE.pBkmk = &rBookmark;
314         pDdeBookmark->SetRefObject(this);
315     }
316     else
317         OSL_ENSURE(false,
318             "SwServerObject::SetNoServer(..)"
319             " - setting an bookmark that is not DDE-capable");
320 }
321 
322 /*  */
323 
324 
325 SwDataChanged::SwDataChanged( const SwPaM& rPam, sal_uInt16 nTyp )
326     : pPam( &rPam ), pPos( 0 ), pDoc( rPam.GetDoc() ), nType( nTyp )
327 {
328     nNode = rPam.GetPoint()->nNode.GetIndex();
329     nCntnt = rPam.GetPoint()->nContent.GetIndex();
330 }
331 
332 
333 SwDataChanged::SwDataChanged( SwDoc* pDc, const SwPosition& rPos, sal_uInt16 nTyp )
334     : pPam( 0 ), pPos( &rPos ), pDoc( pDc ), nType( nTyp )
335 {
336     nNode = rPos.nNode.GetIndex();
337     nCntnt = rPos.nContent.GetIndex();
338 }
339 
340 SwDataChanged::~SwDataChanged()
341 {
342     // JP 09.04.96: nur wenn das Layout vorhanden ist ( also waehrend der
343     //              Eingabe)
344 	if( pDoc->GetCurrentViewShell() )	//swmod 071108//swmod 071225
345     {
346         const ::sfx2::SvLinkSources& rServers = pDoc->GetLinkManager().GetServers();
347 
348         for( sal_uInt16 nCnt = rServers.Count(); nCnt; )
349         {
350             ::sfx2::SvLinkSourceRef refObj( rServers[ --nCnt ] );
351             // noch jemand am Object interessiert ?
352             if( refObj->HasDataLinks() && refObj->ISA( SwServerObject ))
353             {
354                 SwServerObject& rObj = *(SwServerObject*)&refObj;
355                 if( pPos )
356                     rObj.SendDataChanged( *pPos );
357                 else
358                     rObj.SendDataChanged( *pPam );
359             }
360 
361             // sollte jetzt gar keine Verbindung mehr bestehen
362             if( !refObj->HasDataLinks() )
363             {
364                 // dann raus aus der Liste (Object bleibt aber bestehen!)
365                 // falls es noch da ist !!
366                 if( nCnt < rServers.Count() && &refObj == rServers[ nCnt ] )
367                     pDoc->GetLinkManager().RemoveServer( nCnt, 1 );
368             }
369         }
370     }
371 }
372