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: docdde.cxx,v $
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"
39 #include <vcl/svapp.hxx>
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>
49 #include <swserv.hxx> // fuer Server-Funktionalitaet
51 #include <bookmrk.hxx>
52 #include <section.hxx> // fuer SwSectionFmt
53 #include <swtable.hxx> // fuer SwTable
58 #include <MarkManager.hxx>
60 using namespace ::com::sun::star
;
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();
73 ::sw::mark::DdeBookmark
* const pBkmk
= dynamic_cast< ::sw::mark::DdeBookmark
*>(ppMark
->get());
75 (bCaseSensitive
&& (pBkmk
->GetName() == sNameLc
)) ||
76 (!bCaseSensitive
&& GetAppCharClass().lower(pBkmk
->GetName()) == String( sNameLc
)))
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();
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();
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
))
136 if( 0 != ( pTmpTbl
= SwTable::FindTable( rpTableFmt
) ) &&
137 0 != ( pFBox
= pTmpTbl
->GetTabSortBoxes()[0] ) &&
139 &rpTableFmt
->GetDoc()->GetNodes() == &pFBox
->GetSttNd()->GetNodes() )
141 // eine Tabelle im normalen NodesArr
142 ((_FindItem
*)pArgs
)->pTblNd
= (SwTableNode
*)
143 pFBox
->GetSttNd()->FindTableNode();
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;
161 ::sw::mark::DdeBookmark
* const pBkmk
= lcl_FindDdeBookmark(*pMarkManager
, rItem
, bCaseSensitive
);
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
);
172 // gefunden, als erfrage die Daten
173 return SwServerObject( *aPara
.pSectNd
).GetData( rValue
, rMimeType
);
175 if( !bCaseSensitive
)
177 bCaseSensitive
= false;
180 _FindItem
aPara( GetAppCharClass().lower( rItem
));
181 ((SwFrmFmts
*)pTblFrmFmtTbl
)->ForEach( 0, pTblFrmFmtTbl
->Count(),
182 lcl_FindTable
, &aPara
);
185 return SwServerObject( *aPara
.pTblNd
).GetData( rValue
, rMimeType
);
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;
200 ::sw::mark::DdeBookmark
* const pBkmk
= lcl_FindDdeBookmark(*pMarkManager
, rItem
, bCaseSensitive
);
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
);
210 // gefunden, als erfrage die Daten
211 return SwServerObject( *aPara
.pSectNd
).SetData( rMimeType
, rValue
);
213 if( !bCaseSensitive
)
215 bCaseSensitive
= false;
218 String
sItem(GetAppCharClass().lower(rItem
));
219 _FindItem
aPara( sItem
);
220 pTblFrmFmtTbl
->ForEach( 0, pTblFrmFmtTbl
->Count(), lcl_FindTable
, &aPara
);
223 return SwServerObject( *aPara
.pTblNd
).SetData( rMimeType
, rValue
);
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;
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
);
252 _FindItem
aPara(bCaseSensitive
? rItem
: GetAppCharClass().lower(rItem
));
254 ((SwSectionFmts
&)*pSectionFmtTbl
).ForEach(0, pSectionFmtTbl
->Count(), bCaseSensitive
? lcl_FindSectionCaseSensitive
: lcl_FindSectionCaseInsensitive
, &aPara
);
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
);
265 if( !bCaseSensitive
)
267 bCaseSensitive
= false;
270 _FindItem
aPara( GetAppCharClass().lower(rItem
) );
272 ((SwFrmFmts
*)pTblFrmFmtTbl
)->ForEach(0, pTblFrmFmtTbl
->Count(), lcl_FindTable
, &aPara
);
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
);
284 BOOL
SwDoc::SelectServerObj( const String
& rStr
, SwPaM
*& rpPam
,
285 SwNodeRange
*& rpRange
) const
287 // haben wir ueberhaupt das Item vorraetig?
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
);
317 rpRange
= new SwNodeRange( *aPara
.pTblNd
, 0,
318 *aPara
.pTblNd
->EndOfSectionNode(), 1 );
322 else if( sCmp
.EqualsAscii( pMarkToFrame
) )
326 const SwFlyFrmFmt
* pFlyFmt
= FindFlyByName( sName
);
328 0 != ( pIdx
= (SwNodeIndex
*)pFlyFmt
->GetCntnt().GetCntntIdx() ) &&
329 !( pNd
= &pIdx
->GetNode())->IsNoTxtNode() )
331 rpRange
= new SwNodeRange( *pNd
, 1, *pNd
->EndOfSectionNode() );
335 else if( sCmp
.EqualsAscii( pMarkToRegion
) )
337 sItem
= sName
; // wird unten behandelt !
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();
351 rOutlNds
.Seek_Entry( pNd
, &nTmpPos
);
352 rpRange
= new SwNodeRange( aPos
.nNode
, 0, aPos
.nNode
);
354 // dann suche jetzt noch das Ende vom Bereich
356 nTmpPos
< rOutlNds
.Count() &&
357 nLvl
< rOutlNds
[ nTmpPos
]->GetTxtNode()->
358 //GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
359 GetAttrOutlineLevel()-1;//<-end,zhaojianwei
361 ; // es gibt keinen Block
363 if( nTmpPos
< rOutlNds
.Count() )
364 rpRange
->aEnd
= *rOutlNds
[ nTmpPos
];
366 rpRange
->aEnd
= GetNodes().GetEndOfContent();
375 //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
376 bool bCaseSensitive
= true;
379 ::sw::mark::DdeBookmark
* const pBkmk
= lcl_FindDdeBookmark(*pMarkManager
, sItem
, bCaseSensitive
);
382 if(pBkmk
->IsExpanded())
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
);
398 rpRange
= new SwNodeRange( *aPara
.pSectNd
, 1,
399 *aPara
.pSectNd
->EndOfSectionNode() );
404 if( !bCaseSensitive
)
406 bCaseSensitive
= false;