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 #include <com/sun/star/util/SearchOptions.hpp> 28 #include <com/sun/star/util/SearchFlags.hpp> 29 #include <com/sun/star/i18n/TransliterationModules.hpp> 30 31 #include <tools/urlobj.hxx> 32 33 #include <svl/fstathelper.hxx> 34 35 #include <svtools/txtcmp.hxx> 36 37 #include <sfx2/docfile.hxx> 38 39 #include <xmloff/odffields.hxx> 40 41 #include <editeng/unolingu.hxx> 42 43 #include <swtypes.hxx> 44 #include <editsh.hxx> 45 #include <doc.hxx> 46 #include <IDocumentUndoRedo.hxx> 47 #include <pam.hxx> 48 #include <viewopt.hxx> 49 #include <ndtxt.hxx> 50 #include <errhdl.hxx> 51 #include <swundo.hxx> 52 #include <txttxmrk.hxx> 53 #include <edimp.hxx> 54 #include <tox.hxx> 55 #include <doctxm.hxx> 56 #include <docary.hxx> 57 #include <mdiexp.hxx> 58 #include <statstr.hrc> 59 #include <bookmrk.hxx> 60 61 62 using namespace ::com::sun::star; 63 using namespace ::com::sun::star::i18n; 64 using namespace ::com::sun::star::lang; 65 using namespace ::com::sun::star::util; 66 67 /*-------------------------------------------------------------------- 68 Beschreibung: Verzeichnismarkierung ins Dokument einfuegen/loeschen 69 --------------------------------------------------------------------*/ 70 71 72 void SwEditShell::Insert(const SwTOXMark& rMark) 73 { 74 sal_Bool bInsAtPos = rMark.IsAlternativeText(); 75 StartAllAction(); 76 FOREACHPAM_START(this) 77 78 const SwPosition *pStt = PCURCRSR->Start(), 79 *pEnd = PCURCRSR->End(); 80 if( bInsAtPos ) 81 { 82 SwPaM aTmp( *pStt ); 83 GetDoc()->InsertPoolItem( aTmp, rMark, 0 ); 84 } 85 else if( *pEnd != *pStt ) 86 { 87 GetDoc()->InsertPoolItem( *PCURCRSR, rMark, 88 nsSetAttrMode::SETATTR_DONTEXPAND ); 89 } 90 91 FOREACHPAM_END() 92 EndAllAction(); 93 } 94 95 96 97 void SwEditShell::DeleteTOXMark( SwTOXMark* pMark ) 98 { 99 SET_CURR_SHELL( this ); 100 StartAllAction(); 101 102 pDoc->DeleteTOXMark( pMark ); 103 104 EndAllAction(); 105 } 106 107 108 /*-------------------------------------------------------------------- 109 Beschreibung: Alle Verzeichnismarkierungen am SPoint zusammensuchen 110 --------------------------------------------------------------------*/ 111 112 sal_uInt16 SwEditShell::GetCurTOXMarks(SwTOXMarks& rMarks) const 113 { 114 return GetDoc()->GetCurTOXMark( *GetCrsr()->Start(), rMarks ); 115 } 116 117 /* -----------------01.09.99 16:05------------------- 118 119 --------------------------------------------------*/ 120 sal_Bool SwEditShell::IsTOXBaseReadonly(const SwTOXBase& rTOXBase) const 121 { 122 ASSERT( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" ); 123 const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase; 124 return rTOXSect.IsProtect(); 125 } 126 /* -----------------18.10.99 15:53------------------- 127 128 --------------------------------------------------*/ 129 void SwEditShell::SetTOXBaseReadonly(const SwTOXBase& rTOXBase, sal_Bool bReadonly) 130 { 131 ASSERT( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" ); 132 const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase; 133 ((SwTOXBase&)rTOXBase).SetProtected(bReadonly); 134 ASSERT( rTOXSect.SwSection::GetType() == TOX_CONTENT_SECTION, "not a TOXContentSection" ); 135 136 SwSectionData aSectionData(rTOXSect); 137 aSectionData.SetProtectFlag(bReadonly); 138 UpdateSection( GetSectionFmtPos( *rTOXSect.GetFmt() ), aSectionData, 0 ); 139 } 140 141 /* -----------------02.09.99 07:47------------------- 142 143 --------------------------------------------------*/ 144 const SwTOXBase* SwEditShell::GetDefaultTOXBase( TOXTypes eTyp, sal_Bool bCreate ) 145 { 146 return GetDoc()->GetDefaultTOXBase( eTyp, bCreate ); 147 } 148 /* -----------------02.09.99 08:05------------------- 149 150 --------------------------------------------------*/ 151 void SwEditShell::SetDefaultTOXBase(const SwTOXBase& rBase) 152 { 153 GetDoc()->SetDefaultTOXBase(rBase); 154 } 155 156 /*-------------------------------------------------------------------- 157 Beschreibung: Verzeichnis einfuegen, und Inhalt erzeugen 158 --------------------------------------------------------------------*/ 159 160 void SwEditShell::InsertTableOf( const SwTOXBase& rTOX, const SfxItemSet* pSet ) 161 { 162 SET_CURR_SHELL( this ); 163 StartAllAction(); 164 165 SwDocShell* pDocSh = GetDoc()->GetDocShell(); 166 ::StartProgress( STR_STATSTR_TOX_INSERT, 0, 0, pDocSh ); 167 ::SetProgressText( STR_STATSTR_TOX_INSERT, pDocSh ); 168 169 // Einfuegen des Verzeichnisses 170 const SwTOXBaseSection* pTOX = pDoc->InsertTableOf( 171 *GetCrsr()->GetPoint(), rTOX, pSet, sal_True ); 172 ASSERT(pTOX, "Kein aktuelles Verzeichnis"); 173 174 // Formatierung anstossen 175 CalcLayout(); 176 177 // Seitennummern eintragen 178 ((SwTOXBaseSection*)pTOX)->UpdatePageNum(); 179 180 pTOX->SetPosAtStartEnd( *GetCrsr()->GetPoint() ); 181 182 // Fix fuer leere Verzeichnisse 183 InvalidateWindows( aVisArea ); 184 ::EndProgress( pDocSh ); 185 EndAllAction(); 186 } 187 188 /*-------------------------------------------------------------------- 189 Beschreibung: Verzeichnisinhalt erneuern 190 --------------------------------------------------------------------*/ 191 192 sal_Bool SwEditShell::UpdateTableOf( const SwTOXBase& rTOX, const SfxItemSet* pSet ) 193 { 194 sal_Bool bRet = sal_False; 195 196 ASSERT( rTOX.ISA( SwTOXBaseSection ), "keine TOXBaseSection!" ); 197 SwTOXBaseSection* pTOX = (SwTOXBaseSection*)&rTOX; 198 ASSERT(pTOX, "Keine aktuelles Verzeichnis"); 199 const SwSectionNode* pSectNd; 200 if( pTOX && 0 != ( pSectNd = pTOX->GetFmt()->GetSectionNode() ) ) 201 { 202 SwDoc* pMyDoc = GetDoc(); 203 SwDocShell* pDocSh = pMyDoc->GetDocShell(); 204 205 sal_Bool bInIndex = pTOX == GetCurTOX(); 206 SET_CURR_SHELL( this ); 207 StartAllAction(); 208 209 ::StartProgress( STR_STATSTR_TOX_UPDATE, 0, 0, pDocSh ); 210 ::SetProgressText( STR_STATSTR_TOX_UPDATE, pDocSh ); 211 212 pMyDoc->GetIDocumentUndoRedo().StartUndo(UNDO_TOXCHANGE, NULL); 213 214 // Verzeichnisrumpf erzeugen 215 pTOX->Update(pSet); 216 217 // Cursor korrigieren 218 if( bInIndex ) 219 pTOX->SetPosAtStartEnd( *GetCrsr()->GetPoint() ); 220 221 // Formatierung anstossen 222 CalcLayout(); 223 224 // Seitennummern eintragen 225 pTOX->UpdatePageNum(); 226 227 pMyDoc->GetIDocumentUndoRedo().EndUndo(UNDO_TOXCHANGE, NULL); 228 229 ::EndProgress( pDocSh ); 230 EndAllAction(); 231 } 232 return bRet; 233 } 234 235 /*-------------------------------------------------------------------- 236 Beschreibung: Aktuelles Verzeichnis vor oder in dem der Cursor 237 steht 238 --------------------------------------------------------------------*/ 239 240 const SwTOXBase* SwEditShell::GetCurTOX() const 241 { 242 return GetDoc()->GetCurTOX( *GetCrsr()->GetPoint() ); 243 } 244 245 sal_Bool SwEditShell::DeleteTOX( const SwTOXBase& rTOXBase, sal_Bool bDelNodes ) 246 { 247 return GetDoc()->DeleteTOX( (SwTOXBase&)rTOXBase, bDelNodes ); 248 } 249 250 /*-------------------------------------------------------------------- 251 Beschreibung: Typen der Verzeichnisse verwalten 252 --------------------------------------------------------------------*/ 253 254 const SwTOXType* SwEditShell::GetTOXType(TOXTypes eTyp, sal_uInt16 nId) const 255 { 256 return pDoc->GetTOXType(eTyp, nId); 257 } 258 259 /*-------------------------------------------------------------------- 260 Beschreibung: Schluessel fuer Stichwortverzeichnisse verwalten 261 --------------------------------------------------------------------*/ 262 263 sal_uInt16 SwEditShell::GetTOIKeys( SwTOIKeyType eTyp, SvStringsSort& rArr ) const 264 { 265 return GetDoc()->GetTOIKeys( eTyp, rArr ); 266 } 267 268 269 sal_uInt16 SwEditShell::GetTOXCount() const 270 { 271 const SwSectionFmts& rFmts = GetDoc()->GetSections(); 272 sal_uInt16 nRet = 0; 273 for( sal_uInt16 n = rFmts.Count(); n; ) 274 { 275 const SwSection* pSect = rFmts[ --n ]->GetSection(); 276 if( TOX_CONTENT_SECTION == pSect->GetType() && 277 pSect->GetFmt()->GetSectionNode() ) 278 ++nRet; 279 } 280 return nRet; 281 } 282 283 284 const SwTOXBase* SwEditShell::GetTOX( sal_uInt16 nPos ) const 285 { 286 const SwSectionFmts& rFmts = GetDoc()->GetSections(); 287 for( sal_uInt16 n = 0, nCnt = 0; n < rFmts.Count(); ++n ) 288 { 289 const SwSection* pSect = rFmts[ n ]->GetSection(); 290 if( TOX_CONTENT_SECTION == pSect->GetType() && 291 pSect->GetFmt()->GetSectionNode() && 292 nCnt++ == nPos ) 293 { 294 ASSERT( pSect->ISA( SwTOXBaseSection ), "keine TOXBaseSection!" ); 295 return (SwTOXBaseSection*)pSect; 296 } 297 } 298 return 0; 299 } 300 301 302 // nach einlesen einer Datei alle Verzeichnisse updaten 303 void SwEditShell::SetUpdateTOX( sal_Bool bFlag ) 304 { 305 GetDoc()->SetUpdateTOX( bFlag ); 306 } 307 308 309 sal_Bool SwEditShell::IsUpdateTOX() const 310 { 311 return GetDoc()->IsUpdateTOX(); 312 } 313 314 /* -----------------26.08.99 13:49------------------- 315 316 --------------------------------------------------*/ 317 const String& SwEditShell::GetTOIAutoMarkURL() const 318 { 319 return GetDoc()->GetTOIAutoMarkURL(); 320 } 321 /* -----------------26.08.99 13:49------------------- 322 323 --------------------------------------------------*/ 324 void SwEditShell::SetTOIAutoMarkURL(const String& rSet) 325 { 326 GetDoc()->SetTOIAutoMarkURL(rSet); 327 } 328 /* -----------------26.08.99 09:29------------------- 329 330 --------------------------------------------------*/ 331 void SwEditShell::ApplyAutoMark() 332 { 333 StartAllAction(); 334 sal_Bool bDoesUndo = DoesUndo(); 335 DoUndo(sal_False); 336 //1. remove all automatic generated index entries if AutoMarkURL has a 337 // length and the file exists 338 //2. load file 339 //3. select all occurrences of the searched words 340 //4. apply index entries 341 342 String sAutoMarkURL(GetDoc()->GetTOIAutoMarkURL()); 343 if( sAutoMarkURL.Len() && FStatHelper::IsDocument( sAutoMarkURL )) 344 { 345 //1. 346 const SwTOXType* pTOXType = GetTOXType(TOX_INDEX, 0); 347 348 SwTOXMarks aMarks; 349 SwTOXMark::InsertTOXMarks( aMarks, *pTOXType ); 350 for( sal_uInt16 nMark=0; nMark<aMarks.Count(); nMark++ ) 351 { 352 SwTOXMark* pMark = aMarks[nMark]; 353 if(pMark->IsAutoGenerated() && pMark->GetTxtTOXMark()) 354 // mba: test iteration; objects are deleted in iteration 355 DeleteTOXMark(pMark); 356 } 357 358 //2. 359 SfxMedium aMedium( sAutoMarkURL, STREAM_STD_READ, sal_True ); 360 SvStream& rStrm = *aMedium.GetInStream(); 361 const String sZero('0'); 362 Push(); 363 rtl_TextEncoding eChrSet = ::gsl_getSystemTextEncoding(); 364 365 // 366 // SearchOptions to be used in loop below 367 // 368 //SearchAlgorithms eSrchType = SearchAlgorithms_ABSOLUTE; 369 //OUString aSrchStr = rText; 370 sal_Bool bCaseSensitive = sal_True; 371 sal_Bool bWordOnly = sal_False; 372 sal_Bool bSrchInSel = sal_False; 373 sal_Bool bLEV_Relaxed = sal_True; 374 sal_Int32 nLEV_Other = 2; // -> changedChars; 375 sal_Int32 nLEV_Longer = 3; //! -> deletedChars; 376 sal_Int32 nLEV_Shorter = 1; //! -> insertedChars; 377 sal_Int32 nTransliterationFlags = 0; 378 // 379 sal_Int32 nSrchFlags = 0; 380 if (!bCaseSensitive) 381 { 382 nSrchFlags |= SearchFlags::ALL_IGNORE_CASE; 383 nTransliterationFlags |= TransliterationModules_IGNORE_CASE; 384 } 385 if ( bWordOnly) 386 nSrchFlags |= SearchFlags::NORM_WORD_ONLY; 387 if ( bLEV_Relaxed) 388 nSrchFlags |= SearchFlags::LEV_RELAXED; 389 if ( bSrchInSel) 390 nSrchFlags |= (SearchFlags::REG_NOT_BEGINOFLINE | 391 SearchFlags::REG_NOT_ENDOFLINE ); 392 // 393 rtl::OUString sEmpty; 394 SearchOptions aSearchOpt( 395 SearchAlgorithms_ABSOLUTE, nSrchFlags, 396 sEmpty, sEmpty, 397 SvxCreateLocale( LANGUAGE_SYSTEM ), 398 nLEV_Other, nLEV_Longer, nLEV_Shorter, 399 nTransliterationFlags ); 400 401 while( !rStrm.GetError() && !rStrm.IsEof() ) 402 { 403 ByteString aRdLine; 404 rStrm.ReadLine( aRdLine ); 405 406 // # -> comment 407 // ; -> delimiter between entries -> 408 // Format: TextToSearchFor;AlternativeString;PrimaryKey;SecondaryKey;CaseSensitive;WordOnly 409 // Leading and trailing blanks are ignored 410 if( aRdLine.Len() && '#' != aRdLine.GetChar(0) ) 411 { 412 String sLine( aRdLine, eChrSet ); 413 414 xub_StrLen nTokenPos = 0; 415 String sToSelect( sLine.GetToken(0, ';', nTokenPos ) ); 416 if( sToSelect.Len() ) 417 { 418 String sAlternative = sLine.GetToken(0, ';', nTokenPos); 419 String sPrimary = sLine.GetToken(0, ';', nTokenPos); 420 String sSecondary = sLine.GetToken(0, ';', nTokenPos); 421 String sCase = sLine.GetToken(0, ';', nTokenPos); 422 String sWordOnly = sLine.GetToken(0, ';', nTokenPos); 423 424 //3. 425 bCaseSensitive = sCase.Len() && sCase != sZero; 426 bWordOnly = sWordOnly.Len() && sWordOnly != sZero; 427 // 428 if (!bCaseSensitive) 429 { 430 //nSrchFlags |= SearchFlags::ALL_IGNORE_CASE; 431 aSearchOpt.transliterateFlags |= 432 TransliterationModules_IGNORE_CASE; 433 } 434 else 435 { 436 //aSearchOpt.searchFlag &= ~SearchFlags::ALL_IGNORE_CASE; 437 aSearchOpt.transliterateFlags &= 438 ~TransliterationModules_IGNORE_CASE; 439 } 440 if ( bWordOnly) 441 aSearchOpt.searchFlag |= SearchFlags::NORM_WORD_ONLY; 442 else 443 aSearchOpt.searchFlag &= ~SearchFlags::NORM_WORD_ONLY; 444 // 445 aSearchOpt.searchString = sToSelect; 446 447 KillPams(); 448 sal_Bool bCancel; 449 450 // todo/mba: assuming that notes shouldn't be searched 451 sal_Bool bSearchInNotes = sal_False; 452 sal_uLong nRet = Find( aSearchOpt, bSearchInNotes, DOCPOS_START, DOCPOS_END, bCancel, 453 (FindRanges)(FND_IN_SELALL|FND_IN_BODYONLY), 454 sal_False ); 455 456 if(nRet) 457 { 458 SwTOXMark* pTmpMark = new SwTOXMark(pTOXType); 459 if( sPrimary.Len() ) 460 { 461 pTmpMark->SetPrimaryKey( sPrimary ); 462 if( sSecondary.Len() ) 463 pTmpMark->SetSecondaryKey( sSecondary ); 464 } 465 if(sAlternative.Len()) 466 pTmpMark->SetAlternativeText(sAlternative); 467 pTmpMark->SetMainEntry(sal_False); 468 pTmpMark->SetAutoGenerated(sal_True); 469 //4. 470 SwEditShell::Insert(*pTmpMark); 471 } 472 } 473 } 474 } 475 KillPams(); 476 Pop(sal_False); 477 } 478 DoUndo(bDoesUndo); 479 EndAllAction(); 480 } 481 482 483 484