update dev300-m58
[ooovba.git] / sw / source / core / doc / docdde.cxx
blob53ba7a2a5027ed415e2f4ea279c773795cdfd5a1
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: docdde.cxx,v $
10 * $Revision: 1.14 $
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_sw.hxx"
36 #include <stdlib.h>
38 #ifndef _APP_HXX
39 #include <vcl/svapp.hxx>
40 #endif
41 #include <tools/urlobj.hxx>
43 #define _SVSTDARR_STRINGS
44 #include <svtools/svstdarr.hxx>
45 #include <svx/linkmgr.hxx> // LinkManager
46 #include <unotools/charclass.hxx>
47 #include <fmtcntnt.hxx>
48 #include <doc.hxx>
49 #include <swserv.hxx> // fuer Server-Funktionalitaet
50 #include <IMark.hxx>
51 #include <bookmrk.hxx>
52 #include <section.hxx> // fuer SwSectionFmt
53 #include <swtable.hxx> // fuer SwTable
54 #include <node.hxx>
55 #include <ndtxt.hxx>
56 #include <pam.hxx>
57 #include <docary.hxx>
58 #include <MarkManager.hxx>
60 using namespace ::com::sun::star;
62 namespace
65 static ::sw::mark::DdeBookmark* const lcl_FindDdeBookmark(const IDocumentMarkAccess& rMarkAccess, const String& rName, bool bCaseSensitive)
67 //Iterating over all bookmarks, checking DdeBookmarks
68 const ::rtl::OUString sNameLc = bCaseSensitive ? rName : GetAppCharClass().lower(rName);
69 for(IDocumentMarkAccess::const_iterator_t ppMark = rMarkAccess.getMarksBegin();
70 ppMark != rMarkAccess.getMarksEnd();
71 ppMark++)
73 ::sw::mark::DdeBookmark* const pBkmk = dynamic_cast< ::sw::mark::DdeBookmark*>(ppMark->get());
74 if(pBkmk &&
75 (bCaseSensitive && (pBkmk->GetName() == sNameLc)) ||
76 (!bCaseSensitive && GetAppCharClass().lower(pBkmk->GetName()) == String( sNameLc )))
77 return pBkmk;
79 return NULL;
83 struct _FindItem
85 const String& rItem;
86 SwTableNode* pTblNd;
87 SwSectionNode* pSectNd;
89 _FindItem(const String& rS)
90 : rItem(rS), pTblNd(0), pSectNd(0)
94 BOOL lcl_FindSection( const SwSectionFmtPtr& rpSectFmt, void* pArgs, bool bCaseSensitive )
96 SwSection* pSect = rpSectFmt->GetSection();
97 if( pSect )
99 String sNm( bCaseSensitive ? pSect->GetName() : GetAppCharClass().lower( pSect->GetName() ));
100 String sCompare( bCaseSensitive ? ((_FindItem*)pArgs)->rItem : GetAppCharClass().lower( ((_FindItem*)pArgs)->rItem ));
101 if( sNm == sCompare )
103 // gefunden, als erfrage die Daten
104 const SwNodeIndex* pIdx;
105 if( 0 != (pIdx = rpSectFmt->GetCntnt().GetCntntIdx() ) &&
106 &rpSectFmt->GetDoc()->GetNodes() == &pIdx->GetNodes() )
108 // eine Tabelle im normalen NodesArr
109 ((_FindItem*)pArgs)->pSectNd = pIdx->GetNode().GetSectionNode();
110 return FALSE;
112 //nein!! // sollte der Namen schon passen, der Rest aber nicht, dann haben wir
113 // sie nicht. Die Namen sind immer eindeutig.
116 return TRUE; // dann weiter
118 BOOL lcl_FindSectionCaseSensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs )
120 return lcl_FindSection( rpSectFmt, pArgs, true );
122 BOOL lcl_FindSectionCaseInsensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs )
124 return lcl_FindSection( rpSectFmt, pArgs, false );
129 BOOL lcl_FindTable( const SwFrmFmtPtr& rpTableFmt, void* pArgs )
131 String sNm( GetAppCharClass().lower( rpTableFmt->GetName() ));
132 if( sNm.Equals( ((_FindItem*)pArgs)->rItem ))
134 SwTable* pTmpTbl;
135 SwTableBox* pFBox;
136 if( 0 != ( pTmpTbl = SwTable::FindTable( rpTableFmt ) ) &&
137 0 != ( pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
138 pFBox->GetSttNd() &&
139 &rpTableFmt->GetDoc()->GetNodes() == &pFBox->GetSttNd()->GetNodes() )
141 // eine Tabelle im normalen NodesArr
142 ((_FindItem*)pArgs)->pTblNd = (SwTableNode*)
143 pFBox->GetSttNd()->FindTableNode();
144 return FALSE;
146 //nein! // sollte der Namen schon passen, der Rest aber nicht, dann haben wir
147 // sie nicht. Die Namen sind immer eindeutig.
149 return TRUE; // dann weiter
154 bool SwDoc::GetData( const String& rItem, const String& rMimeType,
155 uno::Any & rValue ) const
157 //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
158 bool bCaseSensitive = true;
159 while( true )
161 ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
162 if(pBkmk)
163 return SwServerObject(*pBkmk).GetData(rValue, rMimeType);
165 // haben wir ueberhaupt das Item vorraetig?
166 String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
167 _FindItem aPara( sItem );
168 ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(),
169 bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
170 if( aPara.pSectNd )
172 // gefunden, als erfrage die Daten
173 return SwServerObject( *aPara.pSectNd ).GetData( rValue, rMimeType );
175 if( !bCaseSensitive )
176 break;
177 bCaseSensitive = false;
180 _FindItem aPara( GetAppCharClass().lower( rItem ));
181 ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(),
182 lcl_FindTable, &aPara );
183 if( aPara.pTblNd )
185 return SwServerObject( *aPara.pTblNd ).GetData( rValue, rMimeType );
188 return FALSE;
193 bool SwDoc::SetData( const String& rItem, const String& rMimeType,
194 const uno::Any & rValue )
196 //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
197 bool bCaseSensitive = true;
198 while( true )
200 ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
201 if(pBkmk)
202 return SwServerObject(*pBkmk).SetData(rMimeType, rValue);
204 // haben wir ueberhaupt das Item vorraetig?
205 String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
206 _FindItem aPara( sItem );
207 pSectionFmtTbl->ForEach( 0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
208 if( aPara.pSectNd )
210 // gefunden, als erfrage die Daten
211 return SwServerObject( *aPara.pSectNd ).SetData( rMimeType, rValue );
213 if( !bCaseSensitive )
214 break;
215 bCaseSensitive = false;
218 String sItem(GetAppCharClass().lower(rItem));
219 _FindItem aPara( sItem );
220 pTblFrmFmtTbl->ForEach( 0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara );
221 if( aPara.pTblNd )
223 return SwServerObject( *aPara.pTblNd ).SetData( rMimeType, rValue );
226 return FALSE;
231 ::sfx2::SvLinkSource* SwDoc::CreateLinkSource(const String& rItem)
233 SwServerObject* pObj = NULL;
235 //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
236 bool bCaseSensitive = true;
237 while( true )
239 // bookmarks
240 ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
241 if(pBkmk && pBkmk->IsExpanded()
242 && (0 == (pObj = pBkmk->GetRefObject())))
244 // mark found, but no link yet -> create hotlink
245 pObj = new SwServerObject(*pBkmk);
246 pBkmk->SetRefObject(pObj);
247 GetLinkManager().InsertServer(pObj);
249 if(pObj)
250 return pObj;
252 _FindItem aPara(bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
253 // sections
254 ((SwSectionFmts&)*pSectionFmtTbl).ForEach(0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara);
255 if(aPara.pSectNd
256 && (0 == (pObj = aPara.pSectNd->GetSection().GetObject())))
258 // section found, but no link yet -> create hotlink
259 pObj = new SwServerObject( *aPara.pSectNd );
260 aPara.pSectNd->GetSection().SetRefObject( pObj );
261 GetLinkManager().InsertServer(pObj);
263 if(pObj)
264 return pObj;
265 if( !bCaseSensitive )
266 break;
267 bCaseSensitive = false;
270 _FindItem aPara( GetAppCharClass().lower(rItem) );
271 // tables
272 ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach(0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara);
273 if(aPara.pTblNd
274 && (0 == (pObj = aPara.pTblNd->GetTable().GetObject())))
276 // table found, but no link yet -> create hotlink
277 pObj = new SwServerObject(*aPara.pTblNd);
278 aPara.pTblNd->GetTable().SetRefObject(pObj);
279 GetLinkManager().InsertServer(pObj);
281 return pObj;
284 BOOL SwDoc::SelectServerObj( const String& rStr, SwPaM*& rpPam,
285 SwNodeRange*& rpRange ) const
287 // haben wir ueberhaupt das Item vorraetig?
288 rpPam = 0;
289 rpRange = 0;
291 String sItem( INetURLObject::decode( rStr, INET_HEX_ESCAPE,
292 INetURLObject::DECODE_WITH_CHARSET,
293 RTL_TEXTENCODING_UTF8 ));
295 xub_StrLen nPos = sItem.Search( cMarkSeperator );
297 const CharClass& rCC = GetAppCharClass();
299 // Erweiterung fuer die Bereiche, nicht nur Bookmarks/Bereiche linken,
300 // sondern auch Rahmen(Text!), Tabellen, Gliederungen:
301 if( STRING_NOTFOUND != nPos )
303 BOOL bWeiter = FALSE;
304 String sName( sItem.Copy( 0, nPos ) );
305 String sCmp( sItem.Copy( nPos + 1 ));
306 rCC.toLower( sItem );
308 _FindItem aPara( sName );
310 if( sCmp.EqualsAscii( pMarkToTable ) )
312 rCC.toLower( sName );
313 ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(),
314 lcl_FindTable, &aPara );
315 if( aPara.pTblNd )
317 rpRange = new SwNodeRange( *aPara.pTblNd, 0,
318 *aPara.pTblNd->EndOfSectionNode(), 1 );
319 return TRUE;
322 else if( sCmp.EqualsAscii( pMarkToFrame ) )
324 SwNodeIndex* pIdx;
325 SwNode* pNd;
326 const SwFlyFrmFmt* pFlyFmt = FindFlyByName( sName );
327 if( pFlyFmt &&
328 0 != ( pIdx = (SwNodeIndex*)pFlyFmt->GetCntnt().GetCntntIdx() ) &&
329 !( pNd = &pIdx->GetNode())->IsNoTxtNode() )
331 rpRange = new SwNodeRange( *pNd, 1, *pNd->EndOfSectionNode() );
332 return TRUE;
335 else if( sCmp.EqualsAscii( pMarkToRegion ) )
337 sItem = sName; // wird unten behandelt !
338 bWeiter = TRUE;
340 else if( sCmp.EqualsAscii( pMarkToOutline ) )
342 SwPosition aPos( SwNodeIndex( (SwNodes&)GetNodes() ));
343 if( GotoOutline( aPos, sName ))
345 SwNode* pNd = &aPos.nNode.GetNode();
346 //BYTE nLvl = pNd->GetTxtNode()->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
347 const int nLvl = pNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
349 const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
350 USHORT nTmpPos;
351 rOutlNds.Seek_Entry( pNd, &nTmpPos );
352 rpRange = new SwNodeRange( aPos.nNode, 0, aPos.nNode );
354 // dann suche jetzt noch das Ende vom Bereich
355 for( ++nTmpPos;
356 nTmpPos < rOutlNds.Count() &&
357 nLvl < rOutlNds[ nTmpPos ]->GetTxtNode()->
358 //GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
359 GetAttrOutlineLevel()-1;//<-end,zhaojianwei
360 ++nTmpPos )
361 ; // es gibt keinen Block
363 if( nTmpPos < rOutlNds.Count() )
364 rpRange->aEnd = *rOutlNds[ nTmpPos ];
365 else
366 rpRange->aEnd = GetNodes().GetEndOfContent();
367 return TRUE;
371 if( !bWeiter )
372 return FALSE;
375 //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
376 bool bCaseSensitive = true;
377 while( true )
379 ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, sItem, bCaseSensitive);
380 if(pBkmk)
382 if(pBkmk->IsExpanded())
383 rpPam = new SwPaM(
384 pBkmk->GetMarkPos(),
385 pBkmk->GetOtherMarkPos());
386 return static_cast<bool>(rpPam);
390 _FindItem aPara( bCaseSensitive ? sItem : rCC.lower( sItem ) );
392 if( pSectionFmtTbl->Count() )
394 ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(),
395 bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
396 if( aPara.pSectNd )
398 rpRange = new SwNodeRange( *aPara.pSectNd, 1,
399 *aPara.pSectNd->EndOfSectionNode() );
400 return TRUE;
404 if( !bCaseSensitive )
405 break;
406 bCaseSensitive = false;
408 return FALSE;