xref: /trunk/main/sw/source/core/edit/edtox.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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