1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 27 28 29 #include <stdlib.h> 30 31 #ifndef _APP_HXX 32 #include <vcl/svapp.hxx> 33 #endif 34 #include <tools/urlobj.hxx> 35 36 #define _SVSTDARR_STRINGS 37 #include <svl/svstdarr.hxx> 38 #include <sfx2/linkmgr.hxx> // LinkManager 39 #include <unotools/charclass.hxx> 40 #include <fmtcntnt.hxx> 41 #include <doc.hxx> 42 #include <swserv.hxx> // fuer Server-Funktionalitaet 43 #include <IMark.hxx> 44 #include <bookmrk.hxx> 45 #include <section.hxx> // fuer SwSectionFmt 46 #include <swtable.hxx> // fuer SwTable 47 #include <node.hxx> 48 #include <ndtxt.hxx> 49 #include <pam.hxx> 50 #include <docary.hxx> 51 #include <MarkManager.hxx> 52 53 using namespace ::com::sun::star; 54 55 namespace 56 { 57 58 static ::sw::mark::DdeBookmark* lcl_FindDdeBookmark(const IDocumentMarkAccess& rMarkAccess, const String& rName, bool bCaseSensitive) 59 { 60 //Iterating over all bookmarks, checking DdeBookmarks 61 const ::rtl::OUString sNameLc = bCaseSensitive ? rName : GetAppCharClass().lower(rName); 62 for(IDocumentMarkAccess::const_iterator_t ppMark = rMarkAccess.getMarksBegin(); 63 ppMark != rMarkAccess.getMarksEnd(); 64 ppMark++) 65 { 66 if (::sw::mark::DdeBookmark* const pBkmk = dynamic_cast< ::sw::mark::DdeBookmark*>(ppMark->get())) 67 { 68 if ( 69 (bCaseSensitive && (pBkmk->GetName() == sNameLc)) || 70 (!bCaseSensitive && GetAppCharClass().lower(pBkmk->GetName()) == String(sNameLc)) 71 ) 72 { 73 return pBkmk; 74 } 75 } 76 } 77 return NULL; 78 } 79 } 80 81 struct _FindItem 82 { 83 const String m_Item; 84 SwTableNode* pTblNd; 85 SwSectionNode* pSectNd; 86 87 _FindItem(const String& rS) 88 : m_Item(rS), pTblNd(0), pSectNd(0) 89 {} 90 }; 91 92 sal_Bool lcl_FindSection( const SwSectionFmtPtr& rpSectFmt, void* pArgs, bool bCaseSensitive ) 93 { 94 _FindItem * const pItem( static_cast<_FindItem*>(pArgs) ); 95 SwSection* pSect = rpSectFmt->GetSection(); 96 if( pSect ) 97 { 98 String sNm( (bCaseSensitive) 99 ? pSect->GetSectionName() 100 : GetAppCharClass().lower( pSect->GetSectionName() )); 101 String sCompare( (bCaseSensitive) 102 ? pItem->m_Item 103 : GetAppCharClass().lower( pItem->m_Item ) ); 104 if( sNm == sCompare ) 105 { 106 // gefunden, als erfrage die Daten 107 const SwNodeIndex* pIdx; 108 if( 0 != (pIdx = rpSectFmt->GetCntnt().GetCntntIdx() ) && 109 &rpSectFmt->GetDoc()->GetNodes() == &pIdx->GetNodes() ) 110 { 111 // eine Tabelle im normalen NodesArr 112 pItem->pSectNd = pIdx->GetNode().GetSectionNode(); 113 return sal_False; 114 } 115 //nein!! // sollte der Namen schon passen, der Rest aber nicht, dann haben wir 116 // sie nicht. Die Namen sind immer eindeutig. 117 } 118 } 119 return sal_True; // dann weiter 120 } 121 sal_Bool lcl_FindSectionCaseSensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs ) 122 { 123 return lcl_FindSection( rpSectFmt, pArgs, true ); 124 } 125 sal_Bool lcl_FindSectionCaseInsensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs ) 126 { 127 return lcl_FindSection( rpSectFmt, pArgs, false ); 128 } 129 130 131 132 sal_Bool lcl_FindTable( const SwFrmFmtPtr& rpTableFmt, void* pArgs ) 133 { 134 _FindItem * const pItem( static_cast<_FindItem*>(pArgs) ); 135 String sNm( GetAppCharClass().lower( rpTableFmt->GetName() )); 136 if (sNm.Equals( pItem->m_Item )) 137 { 138 SwTable* pTmpTbl; 139 SwTableBox* pFBox; 140 if( 0 != ( pTmpTbl = SwTable::FindTable( rpTableFmt ) ) && 141 0 != ( pFBox = pTmpTbl->GetTabSortBoxes()[0] ) && 142 pFBox->GetSttNd() && 143 &rpTableFmt->GetDoc()->GetNodes() == &pFBox->GetSttNd()->GetNodes() ) 144 { 145 // eine Tabelle im normalen NodesArr 146 pItem->pTblNd = (SwTableNode*) 147 pFBox->GetSttNd()->FindTableNode(); 148 return sal_False; 149 } 150 //nein! // sollte der Namen schon passen, der Rest aber nicht, dann haben wir 151 // sie nicht. Die Namen sind immer eindeutig. 152 } 153 return sal_True; // dann weiter 154 } 155 156 157 158 bool SwDoc::GetData( const String& rItem, const String& rMimeType, 159 uno::Any & rValue ) const 160 { 161 //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive 162 bool bCaseSensitive = true; 163 while( true ) 164 { 165 ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive); 166 if(pBkmk) 167 return SwServerObject(*pBkmk).GetData(rValue, rMimeType); 168 169 // haben wir ueberhaupt das Item vorraetig? 170 String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem)); 171 _FindItem aPara( sItem ); 172 ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(), 173 bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara ); 174 if( aPara.pSectNd ) 175 { 176 // gefunden, als erfrage die Daten 177 return SwServerObject( *aPara.pSectNd ).GetData( rValue, rMimeType ); 178 } 179 if( !bCaseSensitive ) 180 break; 181 bCaseSensitive = false; 182 } 183 184 _FindItem aPara( GetAppCharClass().lower( rItem )); 185 ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(), 186 lcl_FindTable, &aPara ); 187 if( aPara.pTblNd ) 188 { 189 return SwServerObject( *aPara.pTblNd ).GetData( rValue, rMimeType ); 190 } 191 192 return sal_False; 193 } 194 195 196 197 bool SwDoc::SetData( const String& rItem, const String& rMimeType, 198 const uno::Any & rValue ) 199 { 200 //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive 201 bool bCaseSensitive = true; 202 while( true ) 203 { 204 ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive); 205 if(pBkmk) 206 return SwServerObject(*pBkmk).SetData(rMimeType, rValue); 207 208 // haben wir ueberhaupt das Item vorraetig? 209 String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem)); 210 _FindItem aPara( sItem ); 211 pSectionFmtTbl->ForEach( 0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara ); 212 if( aPara.pSectNd ) 213 { 214 // gefunden, als erfrage die Daten 215 return SwServerObject( *aPara.pSectNd ).SetData( rMimeType, rValue ); 216 } 217 if( !bCaseSensitive ) 218 break; 219 bCaseSensitive = false; 220 } 221 222 String sItem(GetAppCharClass().lower(rItem)); 223 _FindItem aPara( sItem ); 224 pTblFrmFmtTbl->ForEach( 0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara ); 225 if( aPara.pTblNd ) 226 { 227 return SwServerObject( *aPara.pTblNd ).SetData( rMimeType, rValue ); 228 } 229 230 return sal_False; 231 } 232 233 234 235 ::sfx2::SvLinkSource* SwDoc::CreateLinkSource(const String& rItem) 236 { 237 SwServerObject* pObj = NULL; 238 239 //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive 240 bool bCaseSensitive = true; 241 while( true ) 242 { 243 // bookmarks 244 ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive); 245 if(pBkmk && pBkmk->IsExpanded() 246 && (0 == (pObj = pBkmk->GetRefObject()))) 247 { 248 // mark found, but no link yet -> create hotlink 249 pObj = new SwServerObject(*pBkmk); 250 pBkmk->SetRefObject(pObj); 251 GetLinkManager().InsertServer(pObj); 252 } 253 if(pObj) 254 return pObj; 255 256 _FindItem aPara(bCaseSensitive ? rItem : GetAppCharClass().lower(rItem)); 257 // sections 258 ((SwSectionFmts&)*pSectionFmtTbl).ForEach(0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara); 259 if(aPara.pSectNd 260 && (0 == (pObj = aPara.pSectNd->GetSection().GetObject()))) 261 { 262 // section found, but no link yet -> create hotlink 263 pObj = new SwServerObject( *aPara.pSectNd ); 264 aPara.pSectNd->GetSection().SetRefObject( pObj ); 265 GetLinkManager().InsertServer(pObj); 266 } 267 if(pObj) 268 return pObj; 269 if( !bCaseSensitive ) 270 break; 271 bCaseSensitive = false; 272 } 273 274 _FindItem aPara( GetAppCharClass().lower(rItem) ); 275 // tables 276 ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach(0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara); 277 if(aPara.pTblNd 278 && (0 == (pObj = aPara.pTblNd->GetTable().GetObject()))) 279 { 280 // table found, but no link yet -> create hotlink 281 pObj = new SwServerObject(*aPara.pTblNd); 282 aPara.pTblNd->GetTable().SetRefObject(pObj); 283 GetLinkManager().InsertServer(pObj); 284 } 285 return pObj; 286 } 287 288 sal_Bool SwDoc::SelectServerObj( const String& rStr, SwPaM*& rpPam, 289 SwNodeRange*& rpRange ) const 290 { 291 // haben wir ueberhaupt das Item vorraetig? 292 rpPam = 0; 293 rpRange = 0; 294 295 String sItem( INetURLObject::decode( rStr, INET_HEX_ESCAPE, 296 INetURLObject::DECODE_WITH_CHARSET, 297 RTL_TEXTENCODING_UTF8 )); 298 299 xub_StrLen nPos = sItem.Search( cMarkSeperator ); 300 301 const CharClass& rCC = GetAppCharClass(); 302 303 // Erweiterung fuer die Bereiche, nicht nur Bookmarks/Bereiche linken, 304 // sondern auch Rahmen(Text!), Tabellen, Gliederungen: 305 if( STRING_NOTFOUND != nPos ) 306 { 307 sal_Bool bWeiter = sal_False; 308 String sName( sItem.Copy( 0, nPos ) ); 309 String sCmp( sItem.Copy( nPos + 1 )); 310 rCC.toLower( sItem ); 311 312 _FindItem aPara( sName ); 313 314 if( sCmp.EqualsAscii( pMarkToTable ) ) 315 { 316 rCC.toLower( sName ); 317 ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(), 318 lcl_FindTable, &aPara ); 319 if( aPara.pTblNd ) 320 { 321 rpRange = new SwNodeRange( *aPara.pTblNd, 0, 322 *aPara.pTblNd->EndOfSectionNode(), 1 ); 323 return sal_True; 324 } 325 } 326 else if( sCmp.EqualsAscii( pMarkToFrame ) ) 327 { 328 SwNodeIndex* pIdx; 329 SwNode* pNd; 330 const SwFlyFrmFmt* pFlyFmt = FindFlyByName( sName ); 331 if( pFlyFmt && 332 0 != ( pIdx = (SwNodeIndex*)pFlyFmt->GetCntnt().GetCntntIdx() ) && 333 !( pNd = &pIdx->GetNode())->IsNoTxtNode() ) 334 { 335 rpRange = new SwNodeRange( *pNd, 1, *pNd->EndOfSectionNode() ); 336 return sal_True; 337 } 338 } 339 else if( sCmp.EqualsAscii( pMarkToRegion ) ) 340 { 341 sItem = sName; // wird unten behandelt ! 342 bWeiter = sal_True; 343 } 344 else if( sCmp.EqualsAscii( pMarkToOutline ) ) 345 { 346 SwPosition aPos( SwNodeIndex( (SwNodes&)GetNodes() )); 347 if( GotoOutline( aPos, sName )) 348 { 349 SwNode* pNd = &aPos.nNode.GetNode(); 350 //sal_uInt8 nLvl = pNd->GetTxtNode()->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei 351 const int nLvl = pNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end,zhaojianwei 352 353 const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds(); 354 sal_uInt16 nTmpPos; 355 rOutlNds.Seek_Entry( pNd, &nTmpPos ); 356 rpRange = new SwNodeRange( aPos.nNode, 0, aPos.nNode ); 357 358 // dann suche jetzt noch das Ende vom Bereich 359 for( ++nTmpPos; 360 nTmpPos < rOutlNds.Count() && 361 nLvl < rOutlNds[ nTmpPos ]->GetTxtNode()-> 362 //GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei 363 GetAttrOutlineLevel()-1;//<-end,zhaojianwei 364 ++nTmpPos ) 365 ; // es gibt keinen Block 366 367 if( nTmpPos < rOutlNds.Count() ) 368 rpRange->aEnd = *rOutlNds[ nTmpPos ]; 369 else 370 rpRange->aEnd = GetNodes().GetEndOfContent(); 371 return sal_True; 372 } 373 } 374 375 if( !bWeiter ) 376 return sal_False; 377 } 378 379 //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive 380 bool bCaseSensitive = true; 381 while( true ) 382 { 383 ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, sItem, bCaseSensitive); 384 if(pBkmk) 385 { 386 if(pBkmk->IsExpanded()) 387 rpPam = new SwPaM( 388 pBkmk->GetMarkPos(), 389 pBkmk->GetOtherMarkPos()); 390 return static_cast<bool>(rpPam); 391 } 392 393 // 394 _FindItem aPara( bCaseSensitive ? sItem : rCC.lower( sItem ) ); 395 396 if( pSectionFmtTbl->Count() ) 397 { 398 ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(), 399 bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara ); 400 if( aPara.pSectNd ) 401 { 402 rpRange = new SwNodeRange( *aPara.pSectNd, 1, 403 *aPara.pSectNd->EndOfSectionNode() ); 404 return sal_True; 405 406 } 407 } 408 if( !bCaseSensitive ) 409 break; 410 bCaseSensitive = false; 411 } 412 return sal_False; 413 } 414 415