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