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