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