xref: /AOO41X/main/sw/source/core/edit/autofmt.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 
32 #define _SVSTDARR_LONGS
33 #define _SVSTDARR_USHORTS
34 
35 #include <ctype.h>
36 #include <hintids.hxx>
37 
38 #include <svl/svstdarr.hxx>
39 
40 #include <unotools/charclass.hxx>
41 
42 #include <vcl/msgbox.hxx>
43 
44 #include <editeng/boxitem.hxx>
45 #include <editeng/lrspitem.hxx>
46 #include <editeng/brkitem.hxx>
47 #include <editeng/adjitem.hxx>
48 #include <editeng/tstpitem.hxx>
49 #include <editeng/fontitem.hxx>
50 #include <editeng/langitem.hxx>
51 #include <editeng/cscoitem.hxx>
52 #include <editeng/unolingu.hxx>
53 #include <editeng/acorrcfg.hxx>
54 
55 #include <swwait.hxx>
56 #include <fmtpdsc.hxx>
57 #include <fmtanchr.hxx>
58 #include <doc.hxx>
59 #include <IDocumentUndoRedo.hxx>
60 #include <docary.hxx>
61 #include <editsh.hxx>
62 #include <index.hxx>
63 #include <pam.hxx>
64 #include <edimp.hxx>
65 #include <fesh.hxx>
66 #include <swundo.hxx>		// fuer die UndoIds
67 #include <poolfmt.hxx>
68 #include <ndtxt.hxx>
69 #include <txtfrm.hxx>
70 #include <frminf.hxx>
71 #include <pagedesc.hxx>
72 #include <paratr.hxx>
73 #include <swtable.hxx>
74 #include <acorrect.hxx>
75 #include <shellres.hxx>
76 #include <section.hxx>
77 #include <frmatr.hxx>
78 #include <charatr.hxx>
79 #include <mdiexp.hxx>
80 #include <statstr.hrc>
81 #include <comcore.hrc>
82 #include <numrule.hxx>
83 
84 using namespace ::com::sun::star;
85 
86 //-------------------------------------------------------------------
87 
88 //JP 16.12.99: definition:
89 //		from pos cPosEnDash to cPosEmDash all chars changed to endashes,
90 //		from pos cPosEmDash to cPosEnd    all chars changed to emdashes
91 // 		all other chars are changed to the user configuration
92 
93 const sal_Unicode pBulletChar[6] = { '+', '*', '-', 0x2013, 0x2014, 0 };
94 const int cnPosEnDash = 2, cnPosEmDash = 4, cnPosEnd = 5;
95 
96 const sal_Unicode cStarSymbolEnDash = 0x2013;
97 const sal_Unicode cStarSymbolEmDash = 0x2014;
98 
99 
100 SvxSwAutoFmtFlags* SwEditShell::pAutoFmtFlags = 0;
101 
102 // Anzahl von Num-/Bullet-Absatzvorlagen. MAXLEVEL wird demnaechst auf
103 // x erhoeht, die Anzahl Vorlagen aber nicht (Ueberbleibsel aus <= 4.0)
104 const sal_uInt16 cnNumBullColls = 4;
105 
106 class SwAutoFormat
107 {
108 	SvxSwAutoFmtFlags aFlags;
109 	SwPaM aDelPam;				// ein Pam der benutzt werden kann
110 	SwNodeIndex aNdIdx;			// der Index auf den akt. TextNode
111 	SwNodeIndex aEndNdIdx;		// Index auf das Ende vom Bereich
112 
113 	SwEditShell* pEditShell;
114 	SwDoc* pDoc;
115 	SwTxtNode* pAktTxtNd;		// der akt. TextNode
116 	SwTxtFrm* pAktTxtFrm;		// Frame vom akt. TextNode
117 	CharClass* pCharClass;		// Character classification
118 	sal_uLong nEndNdIdx;			// fuer die Prozent-Anzeige
119 	LanguageType eCharClassLang;
120 
121 	sal_uInt16 nLastHeadLvl, nLastCalcHeadLvl;
122 	sal_uInt16 nLastEnumLvl, nLastCalcEnumLvl;
123 	sal_uInt16 nRedlAutoFmtSeqId;
124 
125 	enum
126 	{
127 		NONE = 0,
128 		DELIM = 1,
129 		DIGIT = 2,
130 		CHG = 4,
131 		LOWER_ALPHA = 8,
132 		UPPER_ALPHA = 16,
133 		LOWER_ROMAN = 32,
134 		UPPER_ROMAN = 64,
135 		NO_DELIM = (DIGIT|LOWER_ALPHA|UPPER_ALPHA|LOWER_ROMAN|UPPER_ROMAN)
136 	};
137 
138 	enum Format_Status
139 	{
140 		READ_NEXT_PARA,
141 		TST_EMPTY_LINE,
142 		TST_ALPHA_LINE,
143 		GET_ALL_INFO,
144 		IS_ONE_LINE,
145 		TST_ENUMERIC,
146 		TST_IDENT,
147 		TST_NEG_IDENT,
148 		TST_TXT_BODY,
149 		HAS_FMTCOLL,
150 		IS_ENDE
151 	} eStat;
152 
153 	sal_Bool bEnde : 1;
154 	sal_Bool bEmptyLine : 1;
155 	sal_Bool bMoreLines : 1;
156 
157     static sal_Bool  m_bAskForCancelUndoWhileBufferOverflow;
158     static short m_nActionWhileAutoformatUndoBufferOverflow;
159 
160 
161 	// ------------- private methods -----------------------------
162 	void _GetCharClass( LanguageType eLang );
163 	CharClass& GetCharClass( LanguageType eLang ) const
164 	{
165 		if( !pCharClass || eLang != eCharClassLang )
166 		{
167 			SwAutoFormat* pThis = (SwAutoFormat*)this;
168 			pThis->_GetCharClass( eLang );
169 		}
170 		return *pCharClass;
171 	}
172 
173 
174 	sal_Bool IsSpace( const sal_Unicode c ) const
175 		{ return (' ' == c || '\t' == c || 0x0a == c|| 0x3000 == c /* Jap. space */) ? sal_True : sal_False; }
176 
177 	void SetColl( sal_uInt16 nId, sal_Bool bHdLineOrText = sal_False );
178 	String GoNextPara();
179 	sal_Bool HasObjects( const SwNode& rNd );
180 
181 	// TxtNode Methoden
182 	const SwTxtNode* GetNextNode() const;
183 	sal_Bool IsEmptyLine( const SwTxtNode& rNd ) const
184 		{	return 0 == rNd.GetTxt().Len() ||
185 				rNd.GetTxt().Len() == GetLeadingBlanks( rNd.GetTxt() ); }
186 
187 	sal_Bool IsOneLine( const SwTxtNode& ) const;
188 	sal_Bool IsFastFullLine( const SwTxtNode& ) const;
189 	sal_Bool IsNoAlphaLine( const SwTxtNode&) const;
190 	sal_Bool IsEnumericChar( const SwTxtNode&) const;
191 	sal_Bool IsBlanksInString( const SwTxtNode&) const;
192 	sal_uInt16 CalcLevel( const SwTxtNode&, sal_uInt16 *pDigitLvl = 0 ) const;
193 	xub_StrLen GetBigIndent( xub_StrLen& rAktSpacePos ) const;
194 
195 	String& DelLeadingBlanks( String& rStr ) const;
196 	String& DelTrailingBlanks( String& rStr ) const;
197 	xub_StrLen GetLeadingBlanks( const String& rStr ) const;
198 	xub_StrLen GetTrailingBlanks( const String& rStr ) const;
199 
200 	sal_Bool IsFirstCharCapital( const SwTxtNode& rNd ) const;
201 	sal_uInt16 GetDigitLevel( const SwTxtNode& rTxtNd, xub_StrLen& rPos,
202 							String* pPreFix = 0, String* pPostFix = 0,
203 							String* pNumTypes = 0 ) const;
204 		// hole den FORMATIERTEN TextFrame
205 	SwTxtFrm* GetFrm( const SwTxtNode& rTxtNd ) const;
206 
207 	void BuildIndent();
208 	void BuildText();
209 	void BuildTextIndent();
210 	void BuildEnum( sal_uInt16 nLvl, sal_uInt16 nDigitLevel );
211 	void BuildNegIndent( SwTwips nSpaces );
212 	void BuildHeadLine( sal_uInt16 nLvl );
213 
214 	sal_Bool HasSelBlanks( SwPaM& rPam ) const;
215 	sal_Bool HasBreakAttr( const SwTxtNode& ) const;
216 	void DeleteSel( SwPaM& rPam );
217 	sal_Bool DeleteAktNxtPara( const String& rNxtPara );
218 	// loesche im Node Anfang oder/und Ende
219 	void DeleteAktPara( sal_Bool bStart = sal_True, sal_Bool nEnd = sal_True );
220 	void DelEmptyLine( sal_Bool bTstNextPara = sal_True );
221 		// loesche bei mehrzeiligen Absaetzen die "linken" und/oder
222 		// "rechten" Raender
223 	void DelMoreLinesBlanks( sal_Bool bWithLineBreaks = sal_False );
224 		// loesche den vorherigen Absatz
225 	void DelPrevPara();
226 		// dann lasse doch mal das AutoCorrect auf den akt. TextNode los
227 	void AutoCorrect( xub_StrLen nSttPos = 0 );
228 
229 	sal_Bool CanJoin( const SwTxtNode* pTxtNd ) const
230 	{
231 		return !bEnde && pTxtNd &&
232 			 !IsEmptyLine( *pTxtNd ) &&
233 			 !IsNoAlphaLine( *pTxtNd) &&
234 			 !IsEnumericChar( *pTxtNd ) &&
235 			 ((STRING_MAXLEN - 50 - pTxtNd->GetTxt().Len()) >
236 					pAktTxtNd->GetTxt().Len()) &&
237 			 !HasBreakAttr( *pTxtNd );
238 	}
239 
240 	// ist ein Punkt am Ende ??
241 	sal_Bool IsSentenceAtEnd( const SwTxtNode& rTxtNd ) const;
242 
243 	sal_Bool DoUnderline();
244 	sal_Bool DoTable();
245 
246 	void _SetRedlineTxt( sal_uInt16 nId );
247 	sal_Bool SetRedlineTxt( sal_uInt16 nId )
248 		{ if( aFlags.bWithRedlining )	_SetRedlineTxt( nId );  return sal_True; }
249 	sal_Bool ClearRedlineTxt()
250 		{ if( aFlags.bWithRedlining )	pDoc->SetAutoFmtRedlineComment(0);  return sal_True; }
251 
252 public:
253 	SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFmtFlags& rFlags,
254 				SwNodeIndex* pSttNd = 0, SwNodeIndex* pEndNd = 0 );
255 	~SwAutoFormat() {
256 		delete pCharClass;
257 	}
258 };
259 
260 sal_Bool  SwAutoFormat::m_bAskForCancelUndoWhileBufferOverflow     = sal_True;
261 short SwAutoFormat::m_nActionWhileAutoformatUndoBufferOverflow = RET_YES;
262 
263 const sal_Unicode* StrChr( const sal_Unicode* pSrc, sal_Unicode c )
264 {
265 	while( *pSrc && *pSrc != c )
266 		++pSrc;
267 	return *pSrc ? pSrc : 0;
268 }
269 
270 SwTxtFrm* SwAutoFormat::GetFrm( const SwTxtNode& rTxtNd ) const
271 {
272 	// besorge mal den Frame
273 	const SwCntntFrm *pFrm = rTxtNd.getLayoutFrm( pEditShell->GetLayout() );
274 	ASSERT( pFrm, "zum Autoformat muss das Layout vorhanden sein" );
275 	if( aFlags.bAFmtByInput && !pFrm->IsValid() )
276 	{
277 		SwRect aTmpFrm( pFrm->Frm() );
278 		SwRect aTmpPrt( pFrm->Prt() );
279 		pFrm->Calc();
280 		if( pFrm->Frm() != aTmpFrm || pFrm->Prt() != aTmpPrt ||
281 			( pFrm->IsTxtFrm() && !((SwTxtFrm*)pFrm)->Paint().IsEmpty() ) )
282 			pFrm->SetCompletePaint();
283 	}
284 	return ((SwTxtFrm*)pFrm)->GetFormatted();
285 }
286 
287 void SwAutoFormat::_GetCharClass( LanguageType eLang )
288 {
289 	delete pCharClass;
290 	pCharClass = new CharClass( SvxCreateLocale( eLang ));
291 	eCharClassLang = eLang;
292 }
293 
294 void SwAutoFormat::_SetRedlineTxt( sal_uInt16 nActionId )
295 {
296 	String sTxt;
297 	sal_uInt16 nSeqNo = 0;
298 	if( STR_AUTOFMTREDL_END > nActionId )
299 	{
300 		sTxt = *ViewShell::GetShellRes()->GetAutoFmtNameLst()[ nActionId ];
301 		switch( nActionId )
302 		{
303 		case STR_AUTOFMTREDL_SET_NUMBULET:
304 		case STR_AUTOFMTREDL_DEL_MORELINES:
305 
306 		// AutoCorrect-Actions
307 		case STR_AUTOFMTREDL_USE_REPLACE:
308 		case STR_AUTOFMTREDL_CPTL_STT_WORD:
309 		case STR_AUTOFMTREDL_CPTL_STT_SENT:
310 		case STR_AUTOFMTREDL_TYPO:
311 		case STR_AUTOFMTREDL_UNDER:
312 		case STR_AUTOFMTREDL_BOLD:
313 		case STR_AUTOFMTREDL_FRACTION:
314 		case STR_AUTOFMTREDL_DASH:
315 		case STR_AUTOFMTREDL_ORDINAL:
316         case STR_AUTOFMTREDL_NON_BREAK_SPACE:
317 			nSeqNo = ++nRedlAutoFmtSeqId;
318 			break;
319 		}
320 	}
321 #if OSL_DEBUG_LEVEL > 1
322 	else
323 		sTxt = String::CreateFromAscii(
324 							RTL_CONSTASCII_STRINGPARAM( "Action-Text fehlt" ));
325 #endif
326 
327 	pDoc->SetAutoFmtRedlineComment( &sTxt, nSeqNo );
328 }
329 
330 String SwAutoFormat::GoNextPara()
331 {
332 	SwNode* pNewNd = 0;
333 	do {
334 		//has to be checed twice before and after incrementation
335 		if( aNdIdx.GetIndex() >= aEndNdIdx.GetIndex() )
336 		{
337 			bEnde = sal_True;
338 			return aEmptyStr;
339 		}
340 
341 		aNdIdx++;
342 		if( aNdIdx.GetIndex() >= aEndNdIdx.GetIndex() )
343 		{
344 			bEnde = sal_True;
345 			return aEmptyStr;
346 		}
347 		else
348 			pNewNd = &aNdIdx.GetNode();
349 
350 		// kein TextNode ->
351 		// 		TableNode	: Tabelle ueberspringen
352 		// 		NoTxtNode	: Nodes ueberspringen
353 		// 		EndNode		: Ende erreicht, beenden
354 		if( pNewNd->IsEndNode() )
355 		{
356 			bEnde = sal_True;
357 			return aEmptyStr;
358 		}
359 		else if( pNewNd->IsTableNode() )
360 			aNdIdx = *pNewNd->EndOfSectionNode();
361 		else if( pNewNd->IsSectionNode() )
362 		{
363 			const SwSection& rSect = pNewNd->GetSectionNode()->GetSection();
364 			if( rSect.IsHiddenFlag() || rSect.IsProtectFlag() )
365 				aNdIdx = *pNewNd->EndOfSectionNode();
366 		}
367 	} while( !pNewNd->IsTxtNode() );
368 
369 	if( !aFlags.bAFmtByInput )
370 		::SetProgressState( aNdIdx.GetIndex() + nEndNdIdx - aEndNdIdx.GetIndex(),
371 							pDoc->GetDocShell() );
372 
373 	pAktTxtNd = (SwTxtNode*)pNewNd;
374 	pAktTxtFrm = GetFrm( *pAktTxtNd );
375 	return pAktTxtNd->GetTxt();
376 }
377 
378 sal_Bool SwAutoFormat::HasObjects( const SwNode& rNd )
379 {
380 	// haengt irgend etwas absatzgebundenes am Absatz?
381 	// z.B. Rahmen, DrawObjecte, ..
382 	sal_Bool bRet = sal_False;
383 	const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
384 	for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
385 	{
386 		const SwFmtAnchor& rAnchor = rFmts[ n ]->GetAnchor();
387         if ((FLY_AT_PAGE != rAnchor.GetAnchorId()) &&
388 			rAnchor.GetCntntAnchor() &&
389 			&rAnchor.GetCntntAnchor()->nNode.GetNode() == &rNd )
390 		{
391 			bRet = sal_True;
392 			break;
393 		}
394 	}
395 	return bRet;
396 }
397 
398 const SwTxtNode* SwAutoFormat::GetNextNode() const
399 {
400 	if( aNdIdx.GetIndex()+1 >= aEndNdIdx.GetIndex() )
401 		return 0;
402 	return pDoc->GetNodes()[ aNdIdx.GetIndex() + 1 ]->GetTxtNode();
403 }
404 
405 
406 sal_Bool SwAutoFormat::IsOneLine( const SwTxtNode& rNd ) const
407 {
408 	SwTxtFrmInfo aFInfo( GetFrm( rNd ) );
409 	return aFInfo.IsOneLine();
410 }
411 
412 
413 sal_Bool SwAutoFormat::IsFastFullLine( const SwTxtNode& rNd ) const
414 {
415 	sal_Bool bRet = aFlags.bRightMargin;
416 	if( bRet )
417 	{
418 		SwTxtFrmInfo aFInfo( GetFrm( rNd ) );
419 		bRet = aFInfo.IsFilled( aFlags.nRightMargin );
420 	}
421 	return bRet;
422 }
423 
424 
425 sal_Bool SwAutoFormat::IsEnumericChar( const SwTxtNode& rNd ) const
426 {
427 	const String& rTxt = rNd.GetTxt();
428 	String sTmp( rTxt );
429 	xub_StrLen nBlnks = GetLeadingBlanks( sTmp );
430 	xub_StrLen nLen = rTxt.Len() - nBlnks;
431 	if( !nLen )
432 		return sal_False;
433 
434 	// -, +, * getrennt durch Blank ??
435 	if( 2 < nLen && IsSpace( rTxt.GetChar( nBlnks + 1 ) ) )
436 	{
437 		if( StrChr( pBulletChar, rTxt.GetChar( nBlnks ) ) )
438 			return sal_True;
439 		// sollte an der Position ein Symbolfont existieren ?
440 		SwTxtFrmInfo aFInfo( GetFrm( rNd ) );
441 		if( aFInfo.IsBullet( nBlnks ))
442 			return sal_True;
443 	}
444 
445 	// 1.) / 1. / 1.1.1 / (1). / (1) / ....
446 	return USHRT_MAX != GetDigitLevel( rNd, nBlnks );
447 }
448 
449 
450 sal_Bool SwAutoFormat::IsBlanksInString( const SwTxtNode& rNd ) const
451 {
452 	// suche im String mehr als 5 Blanks/Tabs
453 	String sTmp( rNd.GetTxt() );
454 	DelTrailingBlanks( DelLeadingBlanks( sTmp ));
455 	const sal_Unicode* pTmp = sTmp.GetBuffer();
456 	while( *pTmp )
457 	{
458 		if( IsSpace( *pTmp ) )
459 		{
460 			if( IsSpace( *++pTmp ))		// 2 Space nach einander
461 			{
462 				const sal_Unicode* pStt = pTmp;
463 				while( *pTmp && IsSpace( *++pTmp ))
464 					;
465 				if( 5 <= pTmp - pStt )
466 					return sal_True;
467 			}
468 			else
469 				++pTmp;
470 		}
471 		else
472 			++pTmp;
473 	}
474 	return sal_False;
475 }
476 
477 
478 sal_uInt16 SwAutoFormat::CalcLevel( const SwTxtNode& rNd, sal_uInt16 *pDigitLvl ) const
479 {
480 	sal_uInt16 nLvl = 0, nBlnk = 0;
481 	const String& rTxt = rNd.GetTxt();
482 	if( pDigitLvl )
483 		*pDigitLvl = USHRT_MAX;
484 
485 	if( RES_POOLCOLL_TEXT_MOVE == rNd.GetTxtColl()->GetPoolFmtId() )
486 	{
487 		if( aFlags.bAFmtByInput )
488 		{
489 			nLvl = rNd.GetAutoFmtLvl();
490 			((SwTxtNode&)rNd).SetAutoFmtLvl( 0 );
491 			if( nLvl )
492 				return nLvl;
493 		}
494 		++nLvl;
495 	}
496 
497 
498 	for( xub_StrLen n = 0, nEnd = rTxt.Len(); n < nEnd; ++n )
499 	{
500 		switch( rTxt.GetChar( n ) )
501 		{
502 		case ' ': 	if( 3 == ++nBlnk )
503 						++nLvl, nBlnk = 0;
504 					break;
505 		case '\t':	++nLvl, nBlnk = 0;
506 					break;
507 		default:
508 			if( pDigitLvl )
509 				// Teste auf 1.) / 1. / 1.1.1 / (1). / (1) / ....
510 				*pDigitLvl = GetDigitLevel( rNd, n );
511 			return nLvl;
512 		}
513 	}
514 	return nLvl;
515 }
516 
517 
518 
519 xub_StrLen SwAutoFormat::GetBigIndent( xub_StrLen& rAktSpacePos ) const
520 {
521 	SwTxtFrmInfo aFInfo( GetFrm( *pAktTxtNd ) );
522 	const SwTxtFrm* pNxtFrm = 0;
523 
524 	if( !bMoreLines )
525 	{
526 		const SwTxtNode* pNxtNd = GetNextNode();
527 		if( !CanJoin( pNxtNd ) || !IsOneLine( *pNxtNd ) )
528 			return 0;
529 
530 		pNxtFrm = GetFrm( *pNxtNd );
531 	}
532 
533 	return aFInfo.GetBigIndent( rAktSpacePos, pNxtFrm );
534 }
535 
536 
537 sal_Bool SwAutoFormat::IsNoAlphaLine( const SwTxtNode& rNd ) const
538 {
539 	const String& rStr = rNd.GetTxt();
540 	if( !rStr.Len() )
541 		return sal_False;
542 	// oder besser: ueber die Anzahl von Alpha/Num- und !AN-Zeichen
543 	//				bestimmen.
544 	xub_StrLen nANChar = 0, nBlnk = 0;
545 
546 	CharClass& rCC = GetCharClass( rNd.GetSwAttrSet().GetLanguage().GetLanguage() );
547 	for( xub_StrLen n = 0, nEnd = rStr.Len(); n < nEnd; ++n )
548 		if( IsSpace( rStr.GetChar( n ) ) )
549 			++nBlnk;
550 		else if( rCC.isLetterNumeric( rStr, n ))
551 			++nANChar;
552 
553 	// sind zu 75% keine Alpha-Nummerische-Zeichen, dann sal_True
554 	sal_uLong nLen = rStr.Len() - nBlnk;
555 	nLen = ( nLen * 3 ) / 4;		    // long overflow, if the strlen > sal_uInt16
556 	return xub_StrLen(nLen) < (rStr.Len() - nANChar - nBlnk);
557 }
558 
559 
560 
561 sal_Bool SwAutoFormat::DoUnderline()
562 {
563 	if( !aFlags.bSetBorder )
564 		return sal_False;
565 
566 	const sal_Unicode* pStr = pAktTxtNd->GetTxt().GetBuffer();
567 	int eState = 0;
568 	xub_StrLen nCnt = 0;
569 	while( *pStr )
570 	{
571 //JP 29.03.96: Spaces unterbrechen die Umrandung!
572 //		if( !IsSpace( *pStr ) )
573 		{
574 			int eTmp = 0;
575 			switch( *pStr )
576 			{
577 			case '-': eTmp = 1;	break;
578 			case '_': eTmp = 2;	break;
579 			case '=': eTmp = 3;	break;
580 			case '*': eTmp = 4;	break;
581 			case '~': eTmp = 5;	break;
582 			case '#': eTmp = 6;	break;
583 			default:
584 				return sal_False;
585 			}
586 			if( 0 == eState )
587 				eState = eTmp;
588 			else if( eState != eTmp )
589 				return sal_False;
590 			++nCnt;
591 		}
592 		++pStr;
593 	}
594 
595 	if( 2 < nCnt )
596 	{
597 		// dann unterstreiche mal den vorherigen Absatz, wenn es diesen gibt!
598 		DelEmptyLine( sal_False );
599 		aDelPam.SetMark();
600 		aDelPam.GetMark()->nContent = 0;
601 //JP 19.03.96: kein Underline sondern eine Umrandung setzen!
602 //		pDoc->Insert( aDelPam, SvxUnderlineItem( eState ) );
603 
604 		SvxBorderLine aLine;
605 		switch( eState )
606 		{
607 		case 1:			// einfach, 0,05 pt
608 			aLine.SetOutWidth( DEF_LINE_WIDTH_0 );
609 			break;
610 		case 2:			// einfach, 1,0 pt
611 			aLine.SetOutWidth( DEF_LINE_WIDTH_1 );
612 			break;
613 		case 3:			// doppelt, 1,1 pt
614 			aLine.SetOutWidth( DEF_DOUBLE_LINE0_OUT );
615 			aLine.SetInWidth( DEF_DOUBLE_LINE0_IN );
616 			aLine.SetDistance( DEF_DOUBLE_LINE0_DIST );
617 			break;
618 		case 4:			// doppelt, 4,5 pt
619 			aLine.SetOutWidth( DEF_DOUBLE_LINE4_OUT );
620 			aLine.SetInWidth( DEF_DOUBLE_LINE4_IN );
621 			aLine.SetDistance( DEF_DOUBLE_LINE4_DIST );
622 			break;
623 		case 5:			// doppelt, 6,0 pt
624 			aLine.SetOutWidth( DEF_DOUBLE_LINE5_OUT );
625 			aLine.SetInWidth( DEF_DOUBLE_LINE5_IN );
626 			aLine.SetDistance( DEF_DOUBLE_LINE5_DIST );
627 			break;
628 		case 6:			// doppelt, 9,0 pt
629 			aLine.SetOutWidth( DEF_DOUBLE_LINE6_OUT );
630 			aLine.SetInWidth( DEF_DOUBLE_LINE6_IN );
631 			aLine.SetDistance( DEF_DOUBLE_LINE6_DIST );
632 			break;
633 		}
634         SfxItemSet aSet(pDoc->GetAttrPool(),
635                     RES_PARATR_CONNECT_BORDER, RES_PARATR_CONNECT_BORDER,
636                     RES_BOX, RES_BOX,
637                     0);
638         aSet.Put( SwParaConnectBorderItem( sal_False ) );
639         SvxBoxItem aBox( RES_BOX );
640 		aBox.SetLine( &aLine, BOX_LINE_BOTTOM );
641 		aBox.SetDistance( 42 );		// ~0,75 mm
642         aSet.Put(aBox);
643         pDoc->InsertItemSet( aDelPam, aSet, 0 );
644 
645 		aDelPam.DeleteMark();
646 	}
647 	return 2 < nCnt;
648 }
649 
650 
651 sal_Bool SwAutoFormat::DoTable()
652 {
653 	if( !aFlags.bCreateTable || !aFlags.bAFmtByInput ||
654 		pAktTxtNd->FindTableNode() )
655 		return sal_False;
656 
657 	const String& rTmp = pAktTxtNd->GetTxt();
658 	xub_StrLen nSttPlus = GetLeadingBlanks( rTmp );
659 	xub_StrLen nEndPlus = GetTrailingBlanks( rTmp );
660 	sal_Unicode cChar;
661 
662 	if( 2 > nEndPlus - nSttPlus ||
663 		( '+' != ( cChar = rTmp.GetChar( nSttPlus )) && '|' != cChar ) ||
664 		( '+' != ( cChar = rTmp.GetChar( nEndPlus - 1)) && '|' != cChar ))
665 		return sal_False;
666 
667 	SwTxtFrmInfo aInfo( pAktTxtFrm );
668 
669 	xub_StrLen n = nSttPlus;
670 	const sal_Unicode* pStr = rTmp.GetBuffer() + n;
671 	SvUShorts aPosArr( 5, 5 );
672 
673 	while( *pStr )
674 	{
675 		switch( *pStr )
676 		{
677 		case '-':
678 		case '_':
679 		case '=':
680 		case ' ':
681 		case '\t':
682 			break;
683 
684 		case '+':
685 		case '|':
686 			aPosArr.Insert( static_cast<sal_uInt16>(aInfo.GetCharPos(n)), aPosArr.Count() );
687 			break;
688 
689 		default:
690 			return sal_False;
691 		}
692 		if( ++n == nEndPlus )
693 			break;
694 
695 		++pStr;
696 	}
697 
698 	if( 1 < aPosArr.Count() )
699 	{
700 		// Ausrichtung vom Textnode besorgen:
701 		sal_uInt16 nColCnt = aPosArr.Count() - 1;
702 		SwTwips nSttPos = aPosArr[ 0 ];
703         sal_Int16 eHori;
704 		switch( pAktTxtNd->GetSwAttrSet().GetAdjust().GetAdjust() )
705 		{
706         case SVX_ADJUST_CENTER:     eHori = text::HoriOrientation::CENTER;    break;
707         case SVX_ADJUST_RIGHT:      eHori = text::HoriOrientation::RIGHT;     break;
708 
709 		default:
710 			if( nSttPos )
711 			{
712                 eHori = text::HoriOrientation::NONE;
713 				// dann muss als letztes noch die akt. FrameBreite
714 				// ins Array
715 				aPosArr.Insert( static_cast<sal_uInt16>(pAktTxtFrm->Frm().Width()), aPosArr.Count() );
716 			}
717 			else
718                 eHori = text::HoriOrientation::LEFT;
719 			break;
720 		}
721 
722 		// dann erzeuge eine Tabelle, die den Zeichen entspricht
723 		DelEmptyLine();
724 		SwNodeIndex aIdx( aDelPam.GetPoint()->nNode );
725 		aDelPam.Move( fnMoveForward );
726         pDoc->InsertTable( SwInsertTableOptions( tabopts::ALL_TBL_INS_ATTR , 1 ),
727                            *aDelPam.GetPoint(), 1, nColCnt, eHori,
728                            0, &aPosArr );
729 		aDelPam.GetPoint()->nNode = aIdx;
730 	}
731 	return 1 < aPosArr.Count();
732 }
733 
734 
735 String& SwAutoFormat::DelLeadingBlanks( String& rStr ) const
736 {
737 	xub_StrLen nL;
738 	xub_StrLen n;
739 
740 	for( nL = rStr.Len(), n = 0; n < nL && IsSpace( rStr.GetChar(n) ); ++n )
741 		;
742 	if( n )		// keine Spaces
743 		rStr.Erase( 0, n );
744 	return rStr;
745 }
746 
747 
748 String& SwAutoFormat::DelTrailingBlanks( String& rStr ) const
749 {
750 	xub_StrLen nL = rStr.Len(), n = nL;
751 	if( !nL )
752 		return rStr;
753 
754 	while( --n && IsSpace( rStr.GetChar( n ) )  )
755 		;
756 	if( n+1 != nL )		// keine Spaces
757 		rStr.Erase( n+1 );
758 	return rStr;
759 }
760 
761 
762 xub_StrLen SwAutoFormat::GetLeadingBlanks( const String& rStr ) const
763 {
764 	xub_StrLen nL;
765 	xub_StrLen n;
766 
767 	for( nL = rStr.Len(), n = 0; n < nL && IsSpace( rStr.GetChar( n ) ); ++n )
768 		;
769 	return n;
770 }
771 
772 
773 xub_StrLen SwAutoFormat::GetTrailingBlanks( const String& rStr ) const
774 {
775 	xub_StrLen nL = rStr.Len(), n = nL;
776 	if( !nL )
777 		return 0;
778 
779 	while( --n && IsSpace( rStr.GetChar( n ) )  )
780 		;
781 	return ++n;
782 }
783 
784 
785 sal_Bool SwAutoFormat::IsFirstCharCapital( const SwTxtNode& rNd ) const
786 {
787 	const String& rTxt = rNd.GetTxt();
788 	for( xub_StrLen n = 0, nEnd = rTxt.Len(); n < nEnd; ++n )
789 		if( !IsSpace( rTxt.GetChar( n ) ) )
790 		{
791 			CharClass& rCC = GetCharClass( rNd.GetSwAttrSet().
792 										GetLanguage().GetLanguage() );
793 			sal_Int32 nCharType = rCC.getCharacterType( rTxt, n );
794 			return CharClass::isLetterType( nCharType ) &&
795                    0 != ( i18n::KCharacterType::UPPER &
796 													nCharType );
797 		}
798 	return sal_False;
799 }
800 
801 
802 sal_uInt16 SwAutoFormat::GetDigitLevel( const SwTxtNode& rNd, xub_StrLen& rPos,
803 		String* pPreFix, String* pPostFix, String* pNumTypes ) const
804 {
805 	// Teste auf 1.) / 1. / 1.1.1 / (1). / (1) / ....
806 	const String& rTxt = rNd.GetTxt();
807 	xub_StrLen nPos = rPos;
808 	int eScan = NONE;
809 
810 	sal_uInt16 nStart = 0;
811 	sal_uInt8 nDigitLvl = 0, nDigitCnt = 0;
812 	//count number of parenthesis to assure a sensible order is found
813 	sal_uInt16 nOpeningParentheses = 0;
814 	sal_uInt16 nClosingParentheses = 0;
815 
816 	CharClass& rCC = GetCharClass( rNd.GetSwAttrSet().GetLanguage().GetLanguage() );
817 
818 	while( nPos < rTxt.Len() && nDigitLvl < MAXLEVEL - 1)
819 	{
820 		const sal_Unicode cCurrentChar = rTxt.GetChar( nPos );
821 		if( ('0' <= cCurrentChar &&  '9' >= cCurrentChar) ||
822             (0xff10 <= cCurrentChar &&  0xff19 >= cCurrentChar) )
823 		{
824 			if( eScan & DELIM )
825 			{
826 				if( eScan & CHG )		// nicht wenns mit einer Zahl beginnt
827 				{
828 					++nDigitLvl;
829 					if( pPostFix )
830 						*pPostFix += (sal_Unicode)1;
831 				}
832 
833 				if( pNumTypes )
834 					*pNumTypes += (sal_Unicode)('0' + SVX_NUM_ARABIC);
835 
836 				eScan = eScan | CHG;
837 			}
838 			else if( pNumTypes && !(eScan & DIGIT) )
839 				*pNumTypes += (sal_Unicode)('0' + SVX_NUM_ARABIC);
840 
841 			eScan &= ~DELIM;		// Delim raus
842 			if( 0 != (eScan & ~CHG) && DIGIT != (eScan & ~CHG))
843 				return USHRT_MAX;
844 
845 			eScan |= DIGIT;			// Digit rein
846 			if( 3 == ++nDigitCnt )	// mehr als 2 Nummern sind kein Enum mehr
847 				return USHRT_MAX;
848 
849 			nStart *= 10;
850             nStart += cCurrentChar <= '9' ? cCurrentChar - '0' : cCurrentChar - 0xff10;
851 		}
852 		else if( rCC.isAlpha( rTxt, nPos ) )
853 		{
854 			sal_Bool bIsUpper =
855                 0 != ( i18n::KCharacterType::UPPER &
856 										rCC.getCharacterType( rTxt, nPos ));
857 			sal_Unicode cLow = rCC.toLower( rTxt, nPos, 1 ).GetChar(0), cNumTyp;
858 			int eTmpScan;
859 
860 			// roemische Zeichen sind "mdclxvi". Da man aber eher mal eine
861 			// Numerierung mit c oder d anfangen will, werden diese erstmal
862 			// zu chars und spaeter ggfs. zu romischen Zeichen!
863 //			if( strchr( "mdclxvi", cLow ))
864 #ifdef WITH_ALPHANUM_AS_NUMFMT
865 			//detection of 'c' and 'd' a ROMAN numbering should not be done here
866 			if( 256 > cLow  &&( (eScan & (LOWER_ROMAN|UPPER_ROMAN))
867 									? strchr( "mdclxvi", cLow )
868 									: strchr( "mlxvi", cLow ) ))
869 #else
870 			if( 256 > cLow  && ( strchr( "mdclxvi", cLow ) ))
871 #endif
872 			{
873 				if( bIsUpper )
874 					cNumTyp = '0' + SVX_NUM_ROMAN_UPPER, eTmpScan = UPPER_ROMAN;
875 				else
876 					cNumTyp = '0' + SVX_NUM_ROMAN_LOWER, eTmpScan = LOWER_ROMAN;
877 			}
878 			else if( bIsUpper )
879 				cNumTyp = '0' + SVX_NUM_CHARS_UPPER_LETTER, eTmpScan = UPPER_ALPHA;
880 			else
881 				cNumTyp = '0' + SVX_NUM_CHARS_LOWER_LETTER, eTmpScan = LOWER_ALPHA;
882 
883 
884 			//ggfs. auf roemische Zeichen umschalten (nur bei c/d!)?
885 			if( 1 == nDigitCnt && ( eScan & (UPPER_ALPHA|LOWER_ALPHA) ) &&
886 				( 3 == nStart || 4 == nStart) && 256 > cLow &&
887 				strchr( "mdclxvi", cLow ) &&
888 				(( eScan & UPPER_ALPHA ) ? (eTmpScan & (UPPER_ALPHA|UPPER_ROMAN))
889 										 : (eTmpScan & (LOWER_ALPHA|LOWER_ROMAN))) )
890 			{
891 				sal_Unicode c = '0';
892 				nStart = 3 == nStart ? 100 : 500;
893 				if( UPPER_ALPHA == eTmpScan )
894 					eTmpScan = UPPER_ROMAN, c += SVX_NUM_ROMAN_UPPER;
895 				else
896 					eTmpScan = LOWER_ROMAN, c += SVX_NUM_ROMAN_LOWER;
897 
898 				( eScan &= ~(UPPER_ALPHA|LOWER_ALPHA)) |= eTmpScan;
899 				if( pNumTypes )
900 					pNumTypes->SetChar( pNumTypes->Len() - 1, c );
901 			}
902 
903 			if( eScan & DELIM )
904 			{
905 				if( eScan & CHG )		// nicht wenns mit einer Zahl beginnt
906 				{
907 					++nDigitLvl;
908 					if( pPostFix )
909 						*pPostFix += (sal_Unicode)1;
910 				}
911 
912 				if( pNumTypes )
913 					*pNumTypes += cNumTyp;
914 				eScan = eScan | CHG;
915 			}
916 			else if( pNumTypes && !(eScan & eTmpScan) )
917 				*pNumTypes += cNumTyp;
918 
919 			eScan &= ~DELIM;		// Delim raus
920 
921 			// falls ein andere Type gesetzt ist, brechen wir ab
922 			if( 0 != ( eScan & ~CHG ) && eTmpScan != ( eScan & ~CHG ))
923 				return USHRT_MAX;
924 
925 			if( eTmpScan & (UPPER_ALPHA | LOWER_ALPHA) )
926 			{
927 				// Buchstaben nur zulassen, wenn sie einmalig vorkommen
928                 return USHRT_MAX;
929 			}
930 			else
931 			{
932 				// roemische Zahlen: checke ob das gueltige Zeichen sind
933 				sal_uInt16 nVal;
934 				sal_Bool bError = sal_False;
935 				switch( cLow )
936 				{
937 				case 'm':	nVal = 1000; goto CHECK_ROMAN_1;
938 				case 'd':	nVal =  500; goto CHECK_ROMAN_5;
939 				case 'c':	nVal =  100; goto CHECK_ROMAN_1;
940 				case 'l':	nVal =   50; goto CHECK_ROMAN_5;
941 				case 'x':	nVal =   10; goto CHECK_ROMAN_1;
942 				case 'v':	nVal =    5; goto CHECK_ROMAN_5;
943 
944 CHECK_ROMAN_1:
945 					{
946 						int nMod5 = nStart % (nVal * 5);
947 						int nLast = nStart % nVal;
948 						int n10 = nVal / 10;
949 
950 						if( nMod5 == ((3 * nVal) + n10 ) ||
951 							nMod5 == ((4 * nVal) + n10 ) ||
952 							nLast == n10 )
953 							nStart = static_cast<sal_uInt16>(nStart + (n10 * 8));
954 						else if( nMod5 == 0 ||
955 								 nMod5 == (1 * nVal) ||
956 								 nMod5 == (2 * nVal) )
957 							nStart = nStart + nVal;
958 						else
959 							bError = sal_True;
960 					}
961 					break;
962 
963 CHECK_ROMAN_5:
964 					{
965 						if( ( nStart / nVal ) & 1 )
966 							bError = sal_True;
967 						else
968 						{
969 							int nMod = nStart % nVal;
970 							int n10 = nVal / 5;
971 							if( n10 == nMod )
972 								nStart = static_cast<sal_uInt16>(nStart + (3 * n10));
973 							else if( 0 == nMod )
974 								nStart = nStart + nVal;
975 							else
976 								bError = sal_True;
977 						}
978 					}
979 					break;
980 
981 				case 'i':
982 						if( nStart % 5 >= 3 )
983 							bError = sal_True;
984 						else
985 							nStart += 1;
986 						break;
987 
988 				default:
989 					bError = sal_True;
990 				}
991 
992 				if( bError )
993 					return USHRT_MAX;
994 			}
995 			eScan |= eTmpScan;			// Digit rein
996 			++nDigitCnt;
997 		}
998         else if( (256 > cCurrentChar &&
999                  strchr( ".)(", cCurrentChar )) ||
1000                  0x3002 == cCurrentChar /* Chinese trad. dot */||
1001                  0xff0e == cCurrentChar /* Japanese dot */||
1002                  0xFF08 == cCurrentChar /* opening bracket Chin./Jap.*/||
1003                  0xFF09 == cCurrentChar )/* closing bracket Chin./Jap. */
1004 		{
1005             if(cCurrentChar == '(' || cCurrentChar == 0xFF09)
1006 				nOpeningParentheses++;
1007             else if(cCurrentChar == ')'|| cCurrentChar == 0xFF08)
1008 				nClosingParentheses++;
1009 			// nur wenn noch keine Zahlen gelesen wurden!
1010 			if( pPreFix && !( eScan & ( NO_DELIM | CHG )) )
1011 				*pPreFix += rTxt.GetChar( nPos );
1012 			else if( pPostFix )
1013 				*pPostFix += rTxt.GetChar( nPos );
1014 
1015 			if( NO_DELIM & eScan )
1016 			{
1017 				eScan |= CHG;
1018 				if( pPreFix )
1019 					(*pPreFix += (sal_Unicode)1)
1020 							  += String::CreateFromInt32( nStart );
1021 			}
1022 			eScan &= ~NO_DELIM;		// Delim raus
1023 			eScan |= DELIM;			// Digit rein
1024 			nDigitCnt = 0;
1025 			nStart = 0;
1026 		}
1027 		else
1028 			break;
1029 		++nPos;
1030 	}
1031     if( !( CHG & eScan ) || rPos == nPos ||
1032 		nPos == rTxt.Len() || !IsSpace( rTxt.GetChar( nPos ) ) ||
1033 		(nOpeningParentheses > nClosingParentheses))
1034 		return USHRT_MAX;
1035 
1036 	if( (NO_DELIM & eScan) && pPreFix )		// den letzen nicht vergessen
1037 		(*pPreFix += (sal_Unicode)1) += String::CreateFromInt32( nStart );
1038 
1039 	rPos = nPos;
1040 	return nDigitLvl;		// 0 .. 9 (MAXLEVEL - 1)
1041 }
1042 
1043 
1044 void SwAutoFormat::SetColl( sal_uInt16 nId, sal_Bool bHdLineOrText )
1045 {
1046 	aDelPam.DeleteMark();
1047 	aDelPam.GetPoint()->nNode = aNdIdx;
1048 	aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 );
1049 
1050 	// behalte harte Tabs, Ausrichtung, Sprache, Silbentrennung,
1051 	// DropCaps und fast alle Frame-Attribute
1052 	SfxItemSet aSet( pDoc->GetAttrPool(),
1053 						RES_PARATR_ADJUST, RES_PARATR_ADJUST,
1054 						RES_PARATR_TABSTOP, RES_PARATR_DROP,
1055 						RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
1056 						RES_BACKGROUND, RES_SHADOW,
1057 						0 );
1058 
1059     if( pAktTxtNd->HasSwAttrSet() )
1060 	{
1061 		aSet.Put( *pAktTxtNd->GetpSwAttrSet() );
1062 		// einige Sonderbedingungen:
1063 		// HeaderLine/Textkoerper: nur zentriert oder rechts mitnehmem
1064 		// sonst nur den Blocksatz
1065 		SvxAdjustItem* pAdj;
1066 		if( SFX_ITEM_SET == aSet.GetItemState( RES_PARATR_ADJUST,
1067 						sal_False, (const SfxPoolItem**)&pAdj ))
1068 		{
1069 			SvxAdjust eAdj = pAdj->GetAdjust();
1070 			if( bHdLineOrText ? (SVX_ADJUST_RIGHT != eAdj &&
1071 								 SVX_ADJUST_CENTER != eAdj)
1072 							  : SVX_ADJUST_BLOCK != eAdj )
1073 				aSet.ClearItem( RES_PARATR_ADJUST );
1074 		}
1075 	}
1076 
1077 	pDoc->SetTxtFmtCollByAutoFmt( *aDelPam.GetPoint(), nId, &aSet );
1078 }
1079 
1080 
1081 sal_Bool SwAutoFormat::HasSelBlanks( SwPaM& rPam ) const
1082 {
1083 	// noch ein Blank am Anfang oder Ende ?
1084 	// nicht loeschen, wird wieder eingefuegt.
1085 	SwPosition * pPos = rPam.End();
1086 	xub_StrLen nBlnkPos = pPos->nContent.GetIndex();
1087 	SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
1088 	if( nBlnkPos && nBlnkPos-- < pTxtNd->GetTxt().Len() &&
1089 		( ' ' == pTxtNd->GetTxt().GetChar( nBlnkPos ) ))
1090 // JP 23.08.95: keine Tabs stehen lassen, diese in Blanks wandeln
1091 //        ( ' ' == ( cCh = pTxtNd->GetTxt()[ nBlnkPos ] ) || '\t' == cCh ))
1092 		pPos->nContent--;
1093 	else
1094 	{
1095 		pPos = rPam.GetPoint() == pPos ? rPam.GetMark() : rPam.GetPoint();
1096 		nBlnkPos = pPos->nContent.GetIndex();
1097 		pTxtNd = pPos->nNode.GetNode().GetTxtNode();
1098 		if( nBlnkPos < pTxtNd->GetTxt().Len() &&
1099 			( ' ' == pTxtNd->GetTxt().GetChar( nBlnkPos )))
1100 // JP 23.08.95: keine Tabs stehen lassen, diese in Blanks wandeln
1101 //            ( ' ' == ( cCh = pTxtNd->GetTxt()[ nBlnkPos ] ) || '\t' == cCh ))
1102 			pPos->nContent++;
1103 		else
1104 			return sal_False;
1105 	}
1106 	return sal_True;
1107 }
1108 
1109 
1110 sal_Bool SwAutoFormat::HasBreakAttr( const SwTxtNode& rTxtNd ) const
1111 {
1112     const SfxItemSet* pSet = rTxtNd.GetpSwAttrSet();
1113 	if( !pSet )
1114 		return sal_False;
1115 
1116 	const SfxPoolItem* pItem;
1117 	if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pItem )
1118 		&& SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak() )
1119 		return sal_True;
1120 
1121 	if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, sal_False, &pItem )
1122 		&& ((SwFmtPageDesc*)pItem)->GetPageDesc()
1123 		&& nsUseOnPage::PD_NONE != ((SwFmtPageDesc*)pItem)->GetPageDesc()->GetUseOn() )
1124 		return sal_True;
1125 	return sal_False;
1126 }
1127 
1128 
1129 // ist ein Punkt am Ende ??
1130 sal_Bool SwAutoFormat::IsSentenceAtEnd( const SwTxtNode& rTxtNd ) const
1131 {
1132 	const String& rStr = rTxtNd.GetTxt();
1133 	xub_StrLen n = rStr.Len();
1134 	if( !n )
1135 		return sal_True;
1136 
1137 	while( --n && IsSpace( rStr.GetChar( n  ) ) )
1138 		;
1139 	return '.' == rStr.GetChar( n );
1140 }
1141 
1142 
1143 // loesche im Node Anfang oder/und Ende
1144 void SwAutoFormat::DeleteAktPara( sal_Bool bStart, sal_Bool bEnd )
1145 {
1146 	if( aFlags.bAFmtByInput
1147 		? aFlags.bAFmtByInpDelSpacesAtSttEnd
1148 		: aFlags.bAFmtDelSpacesAtSttEnd )
1149 	{
1150 		// Loesche Blanks am Ende vom akt. und am Anfang vom naechsten
1151 		aDelPam.DeleteMark();
1152 		aDelPam.GetPoint()->nNode = aNdIdx;
1153 		xub_StrLen nPos;
1154 		if( bStart && 0 != ( nPos = GetLeadingBlanks( pAktTxtNd->GetTxt() )))
1155 		{
1156 			aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 );
1157 			aDelPam.SetMark();
1158 			aDelPam.GetPoint()->nContent = nPos;
1159 			DeleteSel( aDelPam );
1160 			aDelPam.DeleteMark();
1161 		}
1162 		if( bEnd && pAktTxtNd->GetTxt().Len() !=
1163 					( nPos = GetTrailingBlanks( pAktTxtNd->GetTxt() )) )
1164 		{
1165 			aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, pAktTxtNd->GetTxt().Len() );
1166 			aDelPam.SetMark();
1167 			aDelPam.GetPoint()->nContent = nPos;
1168 			DeleteSel( aDelPam );
1169 			aDelPam.DeleteMark();
1170 		}
1171 	}
1172 }
1173 
1174 void SwAutoFormat::DeleteSel( SwPaM& rDelPam )
1175 {
1176 	if( aFlags.bWithRedlining )
1177 	{
1178 		// damit der DelPam auch verschoben wird, in den Shell-Cursr-Ring
1179 		// mit aufnehmen !!
1180 		SwPaM* pShCrsr = pEditShell->_GetCrsr();
1181 		SwPaM aTmp( *pAktTxtNd, 0, pShCrsr );
1182 
1183 		Ring *pPrev = rDelPam.GetPrev();
1184 		rDelPam.MoveRingTo( pShCrsr );
1185 
1186 		pEditShell->DeleteSel( rDelPam );
1187 
1188 		// und den Pam wieder herausnehmen:
1189 		Ring *p, *pNext = (Ring*)&rDelPam;
1190 		do {
1191 			p = pNext;
1192 			pNext = p->GetNext();
1193 			p->MoveTo( &rDelPam );
1194 		} while( p != pPrev );
1195 
1196 		aNdIdx = aTmp.GetPoint()->nNode;
1197 		pAktTxtNd = aNdIdx.GetNode().GetTxtNode();
1198 	}
1199 	else
1200 		pEditShell->DeleteSel( rDelPam );
1201 }
1202 
1203 sal_Bool SwAutoFormat::DeleteAktNxtPara( const String& rNxtPara )
1204 {
1205 	// Loesche Blanks am Ende vom akt. und am Anfang vom naechsten
1206 	aDelPam.DeleteMark();
1207 	aDelPam.GetPoint()->nNode = aNdIdx;
1208 	aDelPam.GetPoint()->nContent.Assign( pAktTxtNd,
1209 					GetTrailingBlanks( pAktTxtNd->GetTxt() ) );
1210 	aDelPam.SetMark();
1211 
1212 	aDelPam.GetPoint()->nNode++;
1213 	SwTxtNode* pTNd = aDelPam.GetNode()->GetTxtNode();
1214 	if( !pTNd )
1215 	{
1216 		// dann nur bis zum Ende von Absatz loeschen
1217 		aDelPam.GetPoint()->nNode--;
1218 		aDelPam.GetPoint()->nContent = pAktTxtNd->GetTxt().Len();
1219 	}
1220 	else
1221 		aDelPam.GetPoint()->nContent.Assign( pTNd,
1222 							GetLeadingBlanks( rNxtPara ));
1223 
1224 	// noch ein Blank am Anfang oder Ende ?
1225 	// nicht loeschen, wird wieder eingefuegt.
1226 	sal_Bool bHasBlnks = HasSelBlanks( aDelPam );
1227 
1228 	if( *aDelPam.GetPoint() != *aDelPam.GetMark() )
1229 		DeleteSel( aDelPam );
1230 	aDelPam.DeleteMark();
1231 
1232 	return !bHasBlnks;
1233 }
1234 
1235 
1236 void SwAutoFormat::DelEmptyLine( sal_Bool bTstNextPara )
1237 {
1238 	SetRedlineTxt( STR_AUTOFMTREDL_DEL_EMPTY_PARA );
1239 	// Loesche Blanks den leeren Absatz
1240 	aDelPam.DeleteMark();
1241 	aDelPam.GetPoint()->nNode = aNdIdx;
1242 	aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, pAktTxtNd->GetTxt().Len() );
1243 	aDelPam.SetMark();
1244 
1245 	aDelPam.GetMark()->nNode--;
1246 	SwTxtNode* pTNd = aDelPam.GetNode( sal_False )->GetTxtNode();
1247 	if( pTNd )
1248 		// erstmal den vorherigen Textnode benutzen.
1249 		aDelPam.GetMark()->nContent.Assign( pTNd, pTNd->GetTxt().Len() );
1250 	else if( bTstNextPara )
1251 	{
1252 		// dann versuche den naechsten (am Anfang vom Dok, Tabellen-Zellen,
1253 		// Rahmen, ...
1254 		aDelPam.GetMark()->nNode += 2;
1255 		pTNd = aDelPam.GetNode( sal_False )->GetTxtNode();
1256 		if( pTNd )
1257 		{
1258 			aDelPam.GetMark()->nContent.Assign( pTNd, 0 );
1259 			aDelPam.GetPoint()->nContent = 0;
1260 		}
1261 	}
1262 	else
1263 	{
1264 		aDelPam.GetMark()->nNode = aNdIdx;
1265 		aDelPam.GetMark()->nContent = 0;
1266 		pTNd = pAktTxtNd;
1267 	}
1268 	if( pTNd )
1269 		DeleteSel( aDelPam );
1270 
1271 	aDelPam.DeleteMark();
1272 	ClearRedlineTxt();
1273 }
1274 
1275 
1276 void SwAutoFormat::DelMoreLinesBlanks( sal_Bool bWithLineBreaks )
1277 {
1278 	if( aFlags.bAFmtByInput
1279 		? aFlags.bAFmtByInpDelSpacesBetweenLines
1280 		: aFlags.bAFmtDelSpacesBetweenLines	)
1281 	{
1282 		// loesche alle "Blanks" Links und Rechts vom Einzug
1283 		aDelPam.DeleteMark();
1284 		aDelPam.GetPoint()->nNode = aNdIdx;
1285 		aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 );
1286 
1287 		SwTxtFrmInfo aFInfo( pAktTxtFrm );
1288 		aFInfo.GetSpaces( aDelPam, !aFlags.bAFmtByInput || bWithLineBreaks );
1289 
1290 		SwPaM* pNxt;
1291 		do {
1292 			pNxt = (SwPaM*)aDelPam.GetNext();
1293 			if( pNxt->HasMark() && *pNxt->GetPoint() != *pNxt->GetMark() )
1294 			{
1295 				sal_Bool bHasBlnks = HasSelBlanks( *pNxt );
1296 				DeleteSel( *pNxt );
1297 				if( !bHasBlnks )
1298                 {
1299                     pDoc->InsertString( *pNxt, sal_Unicode(' ') );
1300                 }
1301 			}
1302 
1303 			if( pNxt == &aDelPam )
1304 				break;
1305 			delete pNxt;
1306 		} while( sal_True );
1307 
1308 		aDelPam.DeleteMark();
1309 	}
1310 }
1311 
1312 
1313 		// loesche den vorherigen Absatz
1314 void SwAutoFormat::DelPrevPara()
1315 {
1316 	aDelPam.DeleteMark();
1317 	aDelPam.GetPoint()->nNode = aNdIdx;
1318 	aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 );
1319 	aDelPam.SetMark();
1320 
1321 	aDelPam.GetPoint()->nNode--;
1322 	SwTxtNode* pTNd = aDelPam.GetNode()->GetTxtNode();
1323 	if( pTNd )
1324 	{
1325 		// erstmal den vorherigen Textnode benutzen.
1326 		aDelPam.GetPoint()->nContent.Assign( pTNd, pTNd->GetTxt().Len() );
1327 		DeleteSel( aDelPam );
1328 	}
1329 	aDelPam.DeleteMark();
1330 }
1331 
1332 
1333 void SwAutoFormat::BuildIndent()
1334 {
1335 	SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_INDENT );
1336 
1337 	// lese alle nachfolgenden Absaetze die zu diesem Einzug gehoeren
1338 	sal_Bool bBreak = sal_True;
1339 	if( bMoreLines )
1340 		DelMoreLinesBlanks( sal_True );
1341 	else
1342 		bBreak = !IsFastFullLine( *pAktTxtNd ) ||
1343 				IsBlanksInString( *pAktTxtNd ) ||
1344 				IsSentenceAtEnd( *pAktTxtNd );
1345 	SetColl( RES_POOLCOLL_TEXT_IDENT );
1346 	if( !bBreak )
1347 	{
1348 		SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES );
1349 		const SwTxtNode* pNxtNd = GetNextNode();
1350 		if( pNxtNd && !bEnde )
1351 		{
1352 			do {
1353 				bBreak = !IsFastFullLine( *pNxtNd ) ||
1354 						IsBlanksInString( *pNxtNd ) ||
1355 						IsSentenceAtEnd( *pNxtNd );
1356 				if( DeleteAktNxtPara( pNxtNd->GetTxt() ))
1357                 {
1358                     pDoc->InsertString( aDelPam, sal_Unicode(' ') );
1359                 }
1360 				if( bBreak )
1361 					break;
1362 				pNxtNd = GetNextNode();
1363 			} while( CanJoin( pNxtNd ) &&
1364 					!CalcLevel( *pNxtNd ) );
1365 		}
1366 	}
1367 	DeleteAktPara( sal_True, sal_True );
1368 	AutoCorrect();
1369 }
1370 
1371 
1372 void SwAutoFormat::BuildTextIndent()
1373 {
1374 	SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_TEXT_INDENT);
1375 	// lese alle nachfolgenden Absaetze die zu diesem Einzug gehoeren
1376 	sal_Bool bBreak = sal_True;
1377 	if( bMoreLines )
1378 		DelMoreLinesBlanks( sal_True );
1379 	else
1380 		bBreak = !IsFastFullLine( *pAktTxtNd ) ||
1381 					IsBlanksInString( *pAktTxtNd ) ||
1382 					IsSentenceAtEnd( *pAktTxtNd );
1383 
1384 	if( aFlags.bAFmtByInput )
1385 		pAktTxtNd->SetAutoFmtLvl( (sal_uInt8)CalcLevel( *pAktTxtNd ) );
1386 
1387 	SetColl( RES_POOLCOLL_TEXT_MOVE );
1388 	if( !bBreak )
1389 	{
1390 		SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES );
1391 		const SwTxtNode* pNxtNd = GetNextNode();
1392 		while(	CanJoin( pNxtNd ) &&
1393 				CalcLevel( *pNxtNd ) )
1394 		{
1395 			bBreak = !IsFastFullLine( *pNxtNd ) || IsBlanksInString( *pNxtNd ) ||
1396 					IsSentenceAtEnd( *pNxtNd );
1397 			if( DeleteAktNxtPara( pNxtNd->GetTxt() ) )
1398             {
1399                 pDoc->InsertString( aDelPam, sal_Unicode(' ') );
1400             }
1401 			if( bBreak )
1402 				break;
1403 			pNxtNd = GetNextNode();
1404 		}
1405 	}
1406 	DeleteAktPara( sal_True, sal_True );
1407 	AutoCorrect();
1408 }
1409 
1410 
1411 void SwAutoFormat::BuildText()
1412 {
1413 	SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_TEXT );
1414 	// lese alle nachfolgenden Absaetze die zu diesem Text
1415 	// ohne Einzug gehoeren
1416 	sal_Bool bBreak = sal_True;
1417 	if( bMoreLines )
1418 		DelMoreLinesBlanks();
1419 	else
1420 		bBreak = !IsFastFullLine( *pAktTxtNd ) ||
1421 					IsBlanksInString( *pAktTxtNd ) ||
1422 					IsSentenceAtEnd( *pAktTxtNd );
1423 	SetColl( RES_POOLCOLL_TEXT, sal_True );
1424 	if( !bBreak )
1425 	{
1426 		SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES );
1427 		const SwTxtNode* pNxtNd = GetNextNode();
1428 		while(	CanJoin( pNxtNd ) &&
1429 				!CalcLevel( *pNxtNd ) )
1430 		{
1431 			bBreak = !IsFastFullLine( *pNxtNd ) || IsBlanksInString( *pNxtNd ) ||
1432 					IsSentenceAtEnd( *pNxtNd );
1433 			if( DeleteAktNxtPara( pNxtNd->GetTxt() ) )
1434             {
1435                 pDoc->InsertString( aDelPam, sal_Unicode(' ') );
1436             }
1437 			if( bBreak )
1438 				break;
1439             const SwTxtNode* pCurrNode = pNxtNd;
1440 			pNxtNd = GetNextNode();
1441             if(!pNxtNd || pCurrNode == pNxtNd)
1442                 break;
1443 		}
1444 	}
1445 	DeleteAktPara( sal_True, sal_True );
1446 	AutoCorrect();
1447 }
1448 
1449 
1450 void SwAutoFormat::BuildEnum( sal_uInt16 nLvl, sal_uInt16 nDigitLevel )
1451 {
1452 	SetRedlineTxt( STR_AUTOFMTREDL_SET_NUMBULET );
1453 
1454 	sal_Bool bBreak = sal_True;
1455 
1456 	// als erstes den akt. Einzug bestimmen und die Framebreite bestimmen
1457 	SwTwips nFrmWidth = pAktTxtFrm->Prt().Width();;
1458 	SwTwips nLeftTxtPos;
1459 	{
1460 		const sal_Unicode* pTxt = pAktTxtNd->GetTxt().GetBuffer(), *pSav = pTxt;
1461 		while( IsSpace( *pTxt ) )
1462 			++pTxt;
1463 
1464 		SwTxtFrmInfo aInfo( pAktTxtFrm );
1465 		nLeftTxtPos = aInfo.GetCharPos( static_cast<xub_StrLen>(pTxt - pSav) );
1466         nLeftTxtPos -= pAktTxtNd->GetSwAttrSet().GetLRSpace().GetLeft();
1467     }
1468 
1469 	if( bMoreLines )
1470 		DelMoreLinesBlanks();
1471 	else
1472 		bBreak = !IsFastFullLine( *pAktTxtNd ) ||
1473 					IsBlanksInString( *pAktTxtNd ) ||
1474 					IsSentenceAtEnd( *pAktTxtNd );
1475     sal_Bool bRTL = pEditShell->IsInRightToLeftText();
1476 //	SetColl( RES_POOLCOLL_NUM_LEVEL1 + ( nLvl * 4 ) );
1477 	DeleteAktPara( sal_True, sal_True );
1478 
1479 	sal_Bool bChgBullet = sal_False, bChgEnum = sal_False;
1480 	xub_StrLen nAutoCorrPos = 0;
1481 
1482 	// falls die Numerierung gesetzt werden, die akt. besorgen
1483     // --> OD 2008-02-11 #newlistlevelattrs#
1484     SwNumRule aRule( pDoc->GetUniqueNumRuleName(),
1485                      // --> OD 2008-06-06 #i89178#
1486                      numfunc::GetDefaultPositionAndSpaceMode() );
1487                      // <--
1488     // <--
1489     const SwNumRule* pCur = 0;
1490 	if( aFlags.bSetNumRule && 0 != (pCur = pAktTxtNd->GetNumRule()) )
1491 		aRule = *pCur;
1492 
1493 	// ersetze das Bullet-Zeichen mit dem definiertem
1494 	const String& rStr = pAktTxtNd->GetTxt();
1495 	xub_StrLen nTxtStt = 0, nOrigTxtStt = 0;
1496 	const sal_Unicode* pFndBulletChr;
1497 //	if( aFlags.bAFmtByInput ? aFlags.bSetNumRule : aFlags.bChgEnumNum &&
1498 	if( aFlags.bChgEnumNum &&
1499 		2 < rStr.Len() &&
1500 		0 != ( pFndBulletChr = StrChr( pBulletChar, rStr.GetChar( nTxtStt ) ))
1501 		&& IsSpace( rStr.GetChar( nTxtStt + 1 ) ) )
1502 	{
1503 		if( aFlags.bAFmtByInput )
1504 		{
1505 			if( aFlags.bSetNumRule )
1506 			{
1507 				SwCharFmt* pCFmt = pDoc->GetCharFmtFromPool(
1508 											RES_POOLCHR_BUL_LEVEL );
1509 				bChgBullet = sal_True;
1510 				// wurde das Format schon mal angepasst?
1511 				if( !aRule.GetNumFmt( nLvl ) )
1512 				{
1513 					int nBulletPos = pFndBulletChr - pBulletChar;
1514 					sal_Unicode cBullChar;
1515                     const Font* pBullFnt( 0 );
1516 					if( nBulletPos < cnPosEnDash )
1517 					{
1518 						cBullChar = aFlags.cBullet;
1519 						pBullFnt = &aFlags.aBulletFont;
1520 					}
1521 					else
1522 					{
1523 						cBullChar = nBulletPos < cnPosEmDash
1524 										? cStarSymbolEnDash
1525 										: cStarSymbolEmDash;
1526                         // --> OD 2008-06-03 #i63395#
1527                         // Only apply user defined default bullet font
1528                         if ( numfunc::IsDefBulletFontUserDefined() )
1529                         {
1530                             pBullFnt = &numfunc::GetDefBulletFont();
1531                         }
1532                         // <--
1533 					}
1534 
1535 					sal_uInt16 nAbsPos = lBullIndent;
1536 					sal_uInt16 nSpaceSteps = nLvl
1537 											? sal_uInt16(nLeftTxtPos / nLvl)
1538 											: lBullIndent;
1539 					for( sal_uInt8 n = 0; n < MAXLEVEL; ++n, nAbsPos = nAbsPos + nSpaceSteps )
1540 					{
1541 						SwNumFmt aFmt( aRule.Get( n ) );
1542 						aFmt.SetBulletFont( pBullFnt );
1543 						aFmt.SetBulletChar( cBullChar );
1544 						aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1545                         // #i93908# clear suffix for bullet lists
1546                         aFmt.SetPrefix(::rtl::OUString());
1547                         aFmt.SetSuffix(::rtl::OUString());
1548 						aFmt.SetFirstLineOffset( lBullFirstLineOffset );
1549 						aFmt.SetAbsLSpace( nAbsPos );
1550 						if( !aFmt.GetCharFmt() )
1551 							aFmt.SetCharFmt( pCFmt );
1552                         if( bRTL )
1553                             aFmt.SetNumAdjust( SVX_ADJUST_RIGHT );
1554 
1555 						aRule.Set( n, aFmt );
1556 
1557 						if( n == nLvl &&
1558 							nFrmWidth < ( nSpaceSteps * MAXLEVEL ) )
1559 							nSpaceSteps = static_cast<sal_uInt16>(( nFrmWidth - nLeftTxtPos ) /
1560 												( MAXLEVEL - nLvl ));
1561 					}
1562 				}
1563 			}
1564 		}
1565 		else
1566 		{
1567 			bChgBullet = sal_True;
1568 			SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_BUL_LEVEL1 + ( Min( nLvl, cnNumBullColls ) * 4 )) );
1569 		}
1570 	}
1571 	else
1572 	{
1573 		// dann ist das eine Nummerierung
1574 
1575 		//JP 21.11.97: Der NumLevel wird entweder der DigitLevel oder
1576 		// 				wenn der nicht vorhanden oder 0 ist, durch den
1577 		//				(Einrueckungs-)Level.
1578 
1579 		String aPostFix, aPreFix, aNumTypes;
1580 		if( USHRT_MAX != ( nDigitLevel = GetDigitLevel( *pAktTxtNd, nTxtStt,
1581 										&aPreFix, &aPostFix, &aNumTypes )) )
1582 		{
1583 			bChgEnum = sal_True;
1584 
1585 			// Ebene 0 und Einrueckung dann wird die Ebene durch den linken
1586 			// Einzug und der default NumEinrueckung bestimmt.
1587 			if( !nDigitLevel && nLeftTxtPos )
1588 				nLvl = Min( sal_uInt16( nLeftTxtPos / lNumIndent ),
1589 							sal_uInt16( MAXLEVEL - 1 ) );
1590 			else
1591 				nLvl = nDigitLevel;
1592 		}
1593 
1594 		if( bChgEnum && aFlags.bSetNumRule )
1595 		{
1596 			if( !pCur )			// NumRule anpassen, wenn sie neu ist
1597 			{
1598 				SwCharFmt* pCFmt = pDoc->GetCharFmtFromPool(
1599 											RES_POOLCHR_NUM_LEVEL );
1600 				if( !nDigitLevel )
1601 				{
1602 					SwNumFmt aFmt( aRule.Get( nLvl ) );
1603 					aFmt.SetStart( static_cast<sal_uInt16>(aPreFix.GetToken( 1,
1604 											(sal_Unicode)1 ).ToInt32()));
1605 					aFmt.SetPrefix( aPreFix.GetToken( 0, (sal_Unicode)1 ));
1606 					aFmt.SetSuffix( aPostFix.GetToken( 0, (sal_Unicode)1 ));
1607 					aFmt.SetIncludeUpperLevels( 0 );
1608 
1609 					if( !aFmt.GetCharFmt() )
1610 						aFmt.SetCharFmt( pCFmt );
1611 
1612 					if( aNumTypes.Len() )
1613 						aFmt.SetNumberingType(aNumTypes.GetChar( 0 ) - '0');
1614 
1615                     if( bRTL )
1616                         aFmt.SetNumAdjust( SVX_ADJUST_RIGHT );
1617 					aRule.Set( nLvl, aFmt );
1618 				}
1619 				else
1620 				{
1621 					sal_uInt16 nSpaceSteps = nLvl ? sal_uInt16(nLeftTxtPos / nLvl) : 0;
1622                     sal_uInt8 n;
1623                     for( n = 0; n <= nLvl; ++n )
1624 					{
1625 						SwNumFmt aFmt( aRule.Get( n ) );
1626 
1627 						aFmt.SetStart( static_cast<sal_uInt16>(aPreFix.GetToken( n+1,
1628 													(sal_Unicode)1 ).ToInt32() ));
1629 						if( !n )
1630 							aFmt.SetPrefix( aPreFix.GetToken( n, (sal_Unicode)1 ));
1631 						aFmt.SetSuffix( aPostFix.GetToken( n, (sal_Unicode)1 ));
1632 						aFmt.SetIncludeUpperLevels( MAXLEVEL );
1633 						if( n < aNumTypes.Len() )
1634 							aFmt.SetNumberingType((aNumTypes.GetChar( n ) - '0'));
1635 
1636 						aFmt.SetAbsLSpace( sal_uInt16( nSpaceSteps * n )
1637 											+ lNumIndent );
1638 
1639 						if( !aFmt.GetCharFmt() )
1640 							aFmt.SetCharFmt( pCFmt );
1641                         if( bRTL )
1642                             aFmt.SetNumAdjust( SVX_ADJUST_RIGHT );
1643 
1644 						aRule.Set( n, aFmt );
1645 					}
1646 
1647 					// passt alles vollstaendig in den Frame?
1648 					sal_Bool bDefStep = nFrmWidth < (nSpaceSteps * MAXLEVEL);
1649 					for( ; n < MAXLEVEL; ++n )
1650 					{
1651 						SwNumFmt aFmt( aRule.Get( n ) );
1652 						aFmt.SetIncludeUpperLevels( MAXLEVEL );
1653 						if( bDefStep )
1654 							aFmt.SetAbsLSpace( sal_uInt16( (nLeftTxtPos +
1655                                 SwNumRule::GetNumIndent(static_cast<sal_uInt8>(n-nLvl)))));
1656 						else
1657 							aFmt.SetAbsLSpace( sal_uInt16( nSpaceSteps * n )
1658 												+ lNumIndent );
1659 						aRule.Set( n, aFmt );
1660 					}
1661 				}
1662 			}
1663 		}
1664 		else if( !aFlags.bAFmtByInput )
1665 			SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_NUM_LEVEL1 + ( Min( nLvl, cnNumBullColls ) * 4 ) ));
1666 		else
1667 			bChgEnum = sal_False;
1668 	}
1669 
1670 	if( bChgEnum || bChgBullet )
1671 	{
1672 		aDelPam.DeleteMark();
1673 		aDelPam.GetPoint()->nNode = aNdIdx;
1674 
1675 		if( aFlags.bSetNumRule )
1676 		{
1677 			if( aFlags.bAFmtByInput )
1678 			{
1679 				aDelPam.SetMark();
1680 				aDelPam.GetMark()->nNode++;
1681                 aDelPam.GetNode(sal_False)->GetTxtNode()->SetAttrListLevel( nLvl );
1682 			}
1683 
1684             pAktTxtNd->SetAttrListLevel(nLvl);
1685 			pAktTxtNd->SetNumLSpace( sal_True );
1686 
1687             // --> OD 2008-03-17 #refactorlists#
1688             // start new list
1689             pDoc->SetNumRule( aDelPam, aRule, true );
1690             // <--
1691 			aDelPam.DeleteMark();
1692 
1693 			aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 );
1694 		}
1695 		else
1696 			aDelPam.GetPoint()->nContent.Assign( pAktTxtNd,
1697 						bChgEnum ? (nTxtStt - nOrigTxtStt) : 0 );
1698 		aDelPam.SetMark();
1699 
1700 		if( bChgBullet )
1701 			nTxtStt += 2;
1702 
1703 		while( nTxtStt < rStr.Len() && IsSpace( rStr.GetChar( nTxtStt ) ))
1704 			nTxtStt++;
1705 
1706 		aDelPam.GetPoint()->nContent = nTxtStt - nOrigTxtStt;
1707 		DeleteSel( aDelPam );
1708 
1709 		if( !aFlags.bSetNumRule )
1710 		{
1711 			String sChgStr( '\t' );
1712 			if( bChgBullet )
1713 				sChgStr.Insert( aFlags.cBullet, 0 );
1714             pDoc->InsertString( aDelPam, sChgStr );
1715 
1716 			SfxItemSet aSet( pDoc->GetAttrPool(), aTxtNodeSetRange );
1717 			if( bChgBullet )
1718 			{
1719 				aDelPam.GetPoint()->nContent = 0;
1720 				aDelPam.SetMark();
1721 				aDelPam.GetMark()->nContent = 1;
1722 				SetAllScriptItem( aSet,
1723 					 SvxFontItem( aFlags.aBulletFont.GetFamily(),
1724 								  aFlags.aBulletFont.GetName(),
1725 								  aFlags.aBulletFont.GetStyleName(),
1726 								  aFlags.aBulletFont.GetPitch(),
1727                                   aFlags.aBulletFont.GetCharSet(),
1728                                   RES_CHRATR_FONT ) );
1729 				pDoc->SetFmtItemByAutoFmt( aDelPam, aSet );
1730 				aDelPam.DeleteMark();
1731 				nAutoCorrPos = 2;
1732 				aSet.ClearItem();
1733 			}
1734             SvxTabStopItem aTStops( RES_PARATR_TABSTOP );    aTStops.Insert( SvxTabStop( 0 ));
1735 			aSet.Put( aTStops );
1736 			pDoc->SetFmtItemByAutoFmt( aDelPam, aSet );
1737 		}
1738 	}
1739 
1740 	if( bBreak )
1741 	{
1742 		AutoCorrect( nAutoCorrPos );	   /* Offset wegen Bullet + Tab */
1743 		return;
1744 	}
1745 
1746 	const SwTxtNode* pNxtNd = GetNextNode();
1747 	while( CanJoin( pNxtNd ) &&
1748 			nLvl == CalcLevel( *pNxtNd ) )
1749 	{
1750 		SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES );
1751 		bBreak = !IsFastFullLine( *pNxtNd ) || IsBlanksInString( *pNxtNd ) ||
1752 				IsSentenceAtEnd( *pNxtNd );
1753 		if( DeleteAktNxtPara( pNxtNd->GetTxt() ) )
1754         {
1755             pDoc->InsertString( aDelPam, sal_Unicode(' ') );
1756         }
1757 		if( bBreak )
1758 			break;
1759         const SwTxtNode* pCurrNode = pNxtNd;
1760 		pNxtNd = GetNextNode();
1761         if(!pNxtNd || pCurrNode == pNxtNd)
1762             break;
1763 	}
1764 	DeleteAktPara( sal_False, sal_True );
1765 	AutoCorrect( nAutoCorrPos );
1766 }
1767 
1768 
1769 void SwAutoFormat::BuildNegIndent( SwTwips nSpaces )
1770 {
1771 	SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_NEG_INDENT );
1772 	// Test auf Gegenueberstellung:
1773 	// (n Worte, durch Space/Tabs getrennt, mit gleicher
1774 	//   Einrueckung in der 2.Zeile)
1775 
1776 	// lese alle nachfolgenden Absaetze die zu dieser Aufzaehlung gehoeren
1777 	sal_Bool bBreak = sal_True;
1778 	xub_StrLen nSpacePos, nTxtPos = GetBigIndent( nSpacePos );
1779 	if( bMoreLines )
1780 		DelMoreLinesBlanks( sal_True );
1781 	else
1782 		bBreak = !IsFastFullLine( *pAktTxtNd ) ||
1783 					( !nTxtPos && IsBlanksInString( *pAktTxtNd )) ||
1784 					IsSentenceAtEnd( *pAktTxtNd );
1785 
1786 	SetColl( static_cast<sal_uInt16>( nTxtPos
1787 				? RES_POOLCOLL_CONFRONTATION
1788 				: RES_POOLCOLL_TEXT_NEGIDENT ) );
1789 
1790 	if( nTxtPos )
1791 	{
1792 		const String& rStr = pAktTxtNd->GetTxt();
1793 		sal_Bool bInsTab = sal_True;
1794 
1795 		if( '\t' == rStr.GetChar( nSpacePos+1 ))       // ein Tab, das belassen wir
1796 		{
1797 			--nSpacePos;
1798 			bInsTab = sal_False;
1799 		}
1800 
1801 		xub_StrLen nSpaceStt = nSpacePos;
1802 		while( nSpaceStt && IsSpace( rStr.GetChar( --nSpaceStt ) ) )
1803 			;
1804 		++nSpaceStt;
1805 
1806 		if( bInsTab && '\t' == rStr.GetChar( nSpaceStt ) )		// ein Tab, das belassen wir
1807 		{
1808 			++nSpaceStt;
1809 			bInsTab = sal_False;
1810 		}
1811 
1812 
1813 		aDelPam.DeleteMark();
1814 		aDelPam.GetPoint()->nNode = aNdIdx;
1815 		aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, nSpacePos );
1816 
1817 		// alten Spaces, usw. loeschen
1818 		if( nSpaceStt < nSpacePos )
1819 		{
1820 			aDelPam.SetMark();
1821 			aDelPam.GetMark()->nContent = nSpaceStt;
1822 			DeleteSel( aDelPam );
1823 			if( bInsTab )
1824             {
1825                 pDoc->InsertString( aDelPam, sal_Unicode('\t') );
1826             }
1827         }
1828     }
1829 
1830 	if( !bBreak )
1831 	{
1832 		SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES );
1833 		SwTxtFrmInfo aFInfo( pAktTxtFrm );
1834 		const SwTxtNode* pNxtNd = GetNextNode();
1835 		while(	CanJoin( pNxtNd ) &&
1836 				20 < Abs( (long)(nSpaces - aFInfo.SetFrm(
1837 								GetFrm( *pNxtNd ) ).GetLineStart() ))
1838 			)
1839 		{
1840 			bBreak = !IsFastFullLine( *pNxtNd ) ||
1841 					IsBlanksInString( *pNxtNd ) ||
1842 					IsSentenceAtEnd( *pNxtNd );
1843 			if( DeleteAktNxtPara( pNxtNd->GetTxt() ) )
1844             {
1845                 pDoc->InsertString( aDelPam, sal_Unicode(' ') );
1846             }
1847 			if( bBreak )
1848 				break;
1849 			pNxtNd = GetNextNode();
1850 		}
1851 	}
1852 	DeleteAktPara( sal_True, sal_True );
1853 	AutoCorrect();
1854 }
1855 
1856 
1857 void SwAutoFormat::BuildHeadLine( sal_uInt16 nLvl )
1858 {
1859 	if( aFlags.bWithRedlining )
1860 	{
1861 		String sTxt( *ViewShell::GetShellRes()->GetAutoFmtNameLst()[
1862 									STR_AUTOFMTREDL_SET_TMPL_HEADLINE ] );
1863 		sTxt.SearchAndReplace( String::CreateFromAscii(
1864 									RTL_CONSTASCII_STRINGPARAM( "$(ARG1)" )),
1865 								String::CreateFromInt32( nLvl + 1 ) );
1866 		pDoc->SetAutoFmtRedlineComment( &sTxt );
1867 	}
1868 
1869 	SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + nLvl ), sal_True );
1870 	if( aFlags.bAFmtByInput )
1871 	{
1872 		SwTxtFmtColl& rNxtColl = pAktTxtNd->GetTxtColl()->GetNextTxtFmtColl();
1873 
1874 		DelPrevPara();
1875 
1876 		DeleteAktPara( sal_True, sal_False );
1877 		DeleteAktNxtPara( aEmptyStr );
1878 
1879 		aDelPam.DeleteMark();
1880 		aDelPam.GetPoint()->nNode = aNdIdx.GetIndex() + 1;
1881 		aDelPam.GetPoint()->nContent.Assign( aDelPam.GetCntntNode(), 0 );
1882 		pDoc->SetTxtFmtColl( aDelPam, &rNxtColl );
1883 	}
1884 	else
1885 	{
1886 		DeleteAktPara( sal_True, sal_True );
1887 		AutoCorrect();
1888 	}
1889 }
1890 
1891 
1892 		// dann lasse doch mal das AutoCorrect auf den akt. TextNode los
1893 void SwAutoFormat::AutoCorrect( xub_StrLen nPos )
1894 {
1895 	SvxAutoCorrect* pATst = SvxAutoCorrCfg::Get()->GetAutoCorrect();
1896     long aSvxFlags = pATst->GetFlags( );
1897     bool bReplaceQuote = ( aSvxFlags & ChgQuotes ) > 0;
1898     bool bReplaceSglQuote = ( aSvxFlags & ChgSglQuotes ) > 0;
1899 
1900 	if( aFlags.bAFmtByInput ||
1901 		(!aFlags.bAutoCorrect && !bReplaceQuote && !bReplaceSglQuote &&
1902 		!aFlags.bCptlSttSntnc && !aFlags.bCptlSttWrd &&
1903 		!aFlags.bChgOrdinalNumber &&
1904 		!aFlags.bChgToEnEmDash && !aFlags.bSetINetAttr &&
1905 		!aFlags.bChgWeightUnderl && !aFlags.bAddNonBrkSpace) )
1906 		return;
1907 
1908 	const String* pTxt = &pAktTxtNd->GetTxt();
1909 	if( nPos >= pTxt->Len() )
1910 		return;
1911 
1912 	sal_Bool bGetLanguage = aFlags.bChgOrdinalNumber ||
1913 						aFlags.bChgToEnEmDash || aFlags.bSetINetAttr ||
1914 						aFlags.bCptlSttWrd || aFlags.bCptlSttSntnc ||
1915                         aFlags.bAddNonBrkSpace;
1916 
1917 
1918 	aDelPam.DeleteMark();
1919 	aDelPam.GetPoint()->nNode = aNdIdx;
1920 	aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 );
1921 
1922 	SwAutoCorrDoc aACorrDoc( *pEditShell, aDelPam );
1923 
1924 	SwTxtFrmInfo aFInfo( 0 );
1925 
1926 	xub_StrLen nSttPos, nLastBlank = nPos;
1927 	sal_Bool bFirst = aFlags.bCptlSttSntnc, bFirstSent = bFirst;
1928     sal_Unicode cChar = 0;
1929 
1930 	CharClass& rAppCC = GetAppCharClass();
1931 
1932 	do {
1933 		while( nPos < pTxt->Len() && IsSpace( cChar = pTxt->GetChar( nPos ) ))
1934 			++nPos;
1935 		if( nPos == pTxt->Len() )
1936 			break;		// das wars
1937 
1938 		if( ( ( bReplaceQuote && '\"' == cChar ) ||
1939               ( bReplaceSglQuote && '\'' == cChar ) ) &&
1940 			( !nPos || ' ' == pTxt->GetChar( nPos-1 ) ) )
1941 		{
1942 			// --------------------------------------
1943 			// beachte: Sonderfall Symbolfonts !!!
1944 			if( !aFInfo.GetFrm() )
1945 				aFInfo.SetFrm( GetFrm( *pAktTxtNd ) );
1946 			if( !aFInfo.IsBullet( nPos ))
1947 			{
1948 				SetRedlineTxt( STR_AUTOFMTREDL_TYPO );
1949 				aDelPam.GetPoint()->nContent = nPos;
1950 				sal_Bool bSetHardBlank = sal_False;
1951 
1952 				String sReplace( pATst->GetQuote( aACorrDoc,
1953 									nPos, cChar, sal_True ));
1954 
1955 				aDelPam.SetMark();
1956 				aDelPam.GetPoint()->nContent = nPos+1;
1957 				if( 2 == sReplace.Len() && ' ' == sReplace.GetChar( 1 ))
1958 				{
1959 					sReplace.Erase( 1 );
1960 					bSetHardBlank = sal_True;
1961 				}
1962                 pDoc->ReplaceRange( aDelPam, sReplace, false );
1963 
1964 				if( aFlags.bWithRedlining )
1965 				{
1966 					aNdIdx = aDelPam.GetPoint()->nNode;
1967 					pAktTxtNd = aNdIdx.GetNode().GetTxtNode();
1968 					pTxt = &pAktTxtNd->GetTxt();
1969 					aDelPam.SetMark();
1970 					aFInfo.SetFrm( 0 );
1971 				}
1972 
1973 				nPos += sReplace.Len() - 1;
1974 				aDelPam.DeleteMark();
1975 				if( bSetHardBlank )
1976 				{
1977                     pDoc->InsertString( aDelPam, CHAR_HARDBLANK );
1978 					++nPos;
1979 				}
1980 			}
1981 		}
1982 
1983 		int bCallACorr = sal_False;
1984 		int bBreak = 0;
1985 		if( nPos && IsSpace( pTxt->GetChar( nPos-1 )))
1986 			nLastBlank = nPos;
1987 		for( nSttPos = nPos; !bBreak && nPos < pTxt->Len(); ++nPos )
1988 			switch( cChar = pTxt->GetChar( nPos ) )
1989 			{
1990 			case '\"':
1991 			case '\'':
1992 				if( ( cChar == '\"' && bReplaceQuote ) || ( cChar == '\'' && bReplaceSglQuote ) )
1993 				{
1994 					// --------------------------------------
1995 					// beachte: Sonderfall Symbolfonts !!!
1996 					if( !aFInfo.GetFrm() )
1997 						aFInfo.SetFrm( GetFrm( *pAktTxtNd ) );
1998 					if( !aFInfo.IsBullet( nPos ))
1999 					{
2000 						SetRedlineTxt( STR_AUTOFMTREDL_TYPO );
2001 						sal_Bool bSetHardBlank = sal_False;
2002 						aDelPam.GetPoint()->nContent = nPos;
2003 						String sReplace( pATst->GetQuote( aACorrDoc,
2004 													nPos, cChar, sal_False ));
2005 
2006 						if( 2 == sReplace.Len() && ' ' == sReplace.GetChar( 0 ))
2007 						{
2008 							sReplace.Erase( 0, 1 );
2009 							bSetHardBlank = sal_True;
2010 						}
2011 
2012 						aDelPam.SetMark();
2013 						aDelPam.GetPoint()->nContent = nPos+1;
2014                         pDoc->ReplaceRange( aDelPam, sReplace, false );
2015 
2016 						if( aFlags.bWithRedlining )
2017 						{
2018 							aNdIdx = aDelPam.GetPoint()->nNode;
2019 							pAktTxtNd = aNdIdx.GetNode().GetTxtNode();
2020 							pTxt = &pAktTxtNd->GetTxt();
2021 							aDelPam.SetMark();
2022 							aDelPam.DeleteMark();
2023 							aFInfo.SetFrm( 0 );
2024 						}
2025 
2026 						nPos += sReplace.Len() - 1;
2027 						aDelPam.DeleteMark();
2028 
2029 						if( bSetHardBlank )
2030 						{
2031 							aDelPam.GetPoint()->nContent = nPos;
2032                             pDoc->InsertString( aDelPam, CHAR_HARDBLANK );
2033 							aDelPam.GetPoint()->nContent = ++nPos;
2034 						}
2035 					}
2036 				}
2037 				break;
2038 			case '*':
2039 			case '_':
2040 				if( aFlags.bChgWeightUnderl )
2041 				{
2042 					// --------------------------------------
2043 					// beachte: Sonderfall Symbolfonts !!!
2044 					if( !aFInfo.GetFrm() )
2045 						aFInfo.SetFrm( GetFrm( *pAktTxtNd ) );
2046 					if( !aFInfo.IsBullet( nPos ))
2047 					{
2048 						SetRedlineTxt( '*' == cChar
2049 											? STR_AUTOFMTREDL_BOLD
2050 											: STR_AUTOFMTREDL_UNDER );
2051 
2052 						sal_Unicode cBlank = nSttPos ? pTxt->GetChar(nSttPos - 1) : 0;
2053 						aDelPam.GetPoint()->nContent = nPos;
2054 
2055 						if( pATst->FnChgWeightUnderl( aACorrDoc, *pTxt,
2056 															nSttPos, nPos ))
2057 						{
2058                             if( aFlags.bWithRedlining )
2059                             {
2060                                 aNdIdx = aDelPam.GetPoint()->nNode;
2061                                 pAktTxtNd = aNdIdx.GetNode().GetTxtNode();
2062                                 pTxt = &pAktTxtNd->GetTxt();
2063                                 aDelPam.SetMark();
2064                                 aDelPam.DeleteMark();
2065                                 aFInfo.SetFrm( 0 );
2066                             }
2067                             //#125102# in case of the mode REDLINE_SHOW_DELETE the ** are still contained in pTxt
2068                             if(0 == (pDoc->GetRedlineMode() & nsRedlineMode_t::REDLINE_SHOW_DELETE))
2069                                 nPos = aDelPam.GetPoint()->nContent.GetIndex() - 1;
2070 							// wurde vorm Start ein Zeichen entfernt?
2071 							if( cBlank && cBlank != pTxt->GetChar(nSttPos - 1) )
2072 								--nSttPos;
2073 						}
2074 					}
2075 				}
2076 				break;
2077             case '/':
2078                 if ( aFlags.bAddNonBrkSpace )
2079                 {
2080 			        LanguageType eLang = (bGetLanguage && pAktTxtNd)
2081 										   ? pAktTxtNd->GetLang( nSttPos )
2082 										   : LANGUAGE_SYSTEM;
2083 
2084                     SetRedlineTxt( STR_AUTOFMTREDL_NON_BREAK_SPACE );
2085                     if ( pATst->FnAddNonBrkSpace( aACorrDoc, *pTxt, nSttPos, nPos, eLang ) )
2086                         --nPos;
2087                 }
2088                 break;
2089 
2090 			case '.':
2091 			case '!':
2092 			case '?':
2093 				if( aFlags.bCptlSttSntnc )
2094 					bFirstSent = sal_True;
2095 //alle Wortrenner loesen die Autokorrektur aus!
2096 //				break;
2097 			default:
2098 //alle Wortrenner loesen die Autokorrektur aus!
2099 //			case ' ':
2100 //			case '\t':
2101 				if( !( rAppCC.isLetterNumeric( *pTxt, nPos )
2102                         || '/' == cChar )) //  '/' should not be a word seperator (e.g. '1/2' needs to be handled as one word for replacement)
2103 				{
2104 					--nPos;		// ++nPos von dem for ungueltig machen !
2105 					++bBreak;
2106 				}
2107 				break;
2108 			}
2109 
2110 		if( nPos == nSttPos )
2111 		{
2112 			if( ++nPos == pTxt->Len() )
2113 				bCallACorr = sal_True;
2114 		}
2115 		else
2116 			bCallACorr = sal_True;
2117 
2118 
2119 		if( bCallACorr )
2120 		{
2121 			bCallACorr = sal_False;
2122 			aDelPam.GetPoint()->nContent = nPos;
2123 			SetRedlineTxt( STR_AUTOFMTREDL_USE_REPLACE );
2124 			if( aFlags.bAutoCorrect &&
2125 				aACorrDoc.ChgAutoCorrWord( nSttPos, nPos, *pATst, 0 ) )
2126 			{
2127 				nPos = aDelPam.GetPoint()->nContent.GetIndex();
2128 
2129 				if( aFlags.bWithRedlining )
2130 				{
2131 					aNdIdx = aDelPam.GetPoint()->nNode;
2132 					pAktTxtNd = aNdIdx.GetNode().GetTxtNode();
2133 					pTxt = &pAktTxtNd->GetTxt();
2134 					aDelPam.SetMark();
2135 					aDelPam.DeleteMark();
2136 				}
2137 
2138 				continue;		// nichts weiter mehr abpruefen
2139 			}
2140 
2141 			LanguageType eLang = (bGetLanguage && pAktTxtNd)
2142 										   ? pAktTxtNd->GetLang( nSttPos )
2143 										   : LANGUAGE_SYSTEM;
2144 
2145             if ( aFlags.bAddNonBrkSpace )
2146             {
2147                 SetRedlineTxt( STR_AUTOFMTREDL_NON_BREAK_SPACE );
2148                 pATst->FnAddNonBrkSpace( aACorrDoc, *pTxt, nSttPos, nPos, eLang );
2149             }
2150 
2151 			if( ( aFlags.bChgOrdinalNumber &&
2152 					SetRedlineTxt( STR_AUTOFMTREDL_ORDINAL ) &&
2153 					pATst->FnChgOrdinalNumber( aACorrDoc, *pTxt, nSttPos, nPos, eLang ) ) ||
2154 				( aFlags.bChgToEnEmDash &&
2155 					SetRedlineTxt( STR_AUTOFMTREDL_DASH ) &&
2156 					pATst->FnChgToEnEmDash( aACorrDoc, *pTxt, nSttPos, nPos, eLang ) ) ||
2157 				( aFlags.bSetINetAttr &&
2158 					( nPos == pTxt->Len() || IsSpace( pTxt->GetChar( nPos )) ) &&
2159 					SetRedlineTxt( STR_AUTOFMTREDL_DETECT_URL ) &&
2160 					pATst->FnSetINetAttr( aACorrDoc, *pTxt, nLastBlank, nPos, eLang ) ) )
2161 					nPos = aDelPam.GetPoint()->nContent.GetIndex();
2162 			else
2163 			{
2164 				// Zwei Grossbuchstaben am Wort-Anfang ??
2165 				if( aFlags.bCptlSttWrd )
2166 				{
2167 					SetRedlineTxt( STR_AUTOFMTREDL_CPTL_STT_WORD );
2168 					pATst->FnCptlSttWrd( aACorrDoc, *pTxt, nSttPos, nPos, eLang );
2169 				}
2170 				// Grossbuchstabe am Satz-Anfang ??
2171 				if( aFlags.bCptlSttSntnc && bFirst )
2172 				{
2173 					SetRedlineTxt( STR_AUTOFMTREDL_CPTL_STT_SENT );
2174 					pATst->FnCptlSttSntnc( aACorrDoc, *pTxt, sal_True, nSttPos, nPos, eLang);
2175 					bFirst = sal_False;
2176 				}
2177 
2178 				bFirst = bFirstSent;
2179 				bFirstSent = sal_False;
2180 
2181 				if( aFlags.bWithRedlining )
2182 				{
2183 					aNdIdx = aDelPam.GetPoint()->nNode;
2184 					pAktTxtNd = aNdIdx.GetNode().GetTxtNode();
2185 					pTxt = &pAktTxtNd->GetTxt();
2186 					aDelPam.SetMark();
2187 					aDelPam.DeleteMark();
2188 				}
2189 			}
2190 		}
2191 	} while( nPos < pTxt->Len() );
2192 	ClearRedlineTxt();
2193 }
2194 
2195 
2196 SwAutoFormat::SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFmtFlags& rFlags,
2197 							SwNodeIndex* pSttNd, SwNodeIndex* pEndNd )
2198 	: aFlags( rFlags ),
2199 	aDelPam( pEdShell->GetDoc()->GetNodes().GetEndOfExtras() ),
2200 	aNdIdx( pEdShell->GetDoc()->GetNodes().GetEndOfExtras(), +1 ),
2201 	aEndNdIdx( pEdShell->GetDoc()->GetNodes().GetEndOfContent() ),
2202 	pEditShell( pEdShell ),
2203 	pDoc( pEdShell->GetDoc() ),
2204 	pAktTxtNd( 0 ), pAktTxtFrm( 0 ),
2205 	pCharClass( 0 ),
2206 	nRedlAutoFmtSeqId( 0 )
2207 {
2208 	ASSERT( (pSttNd && pEndNd) || (!pSttNd && !pEndNd),
2209 			"Kein Bereich angegeben" );
2210 
2211 	if( aFlags.bSetNumRule && !aFlags.bAFmtByInput )
2212 		aFlags.bSetNumRule = sal_False;
2213 
2214 	sal_Bool bReplaceStyles = !aFlags.bAFmtByInput || aFlags.bReplaceStyles;
2215 
2216     const SwTxtNode* pNxtNd = 0;
2217     sal_Bool bNxtEmpty = sal_False;
2218     sal_Bool bNxtAlpha = sal_False;
2219     sal_uInt16 nNxtLevel = 0;
2220 
2221 	// setze den Bereich zum Autoformatieren
2222 	if( pSttNd )
2223 	{
2224 		aNdIdx = *pSttNd;
2225 		aNdIdx--;			// fuer GoNextPara, ein Absatz davor
2226 		aEndNdIdx = *pEndNd;
2227 		aEndNdIdx++;
2228 
2229 		// teste den vorhergehenden TextNode
2230 		pNxtNd = aNdIdx.GetNode().GetTxtNode();
2231 		bEmptyLine = !pNxtNd ||
2232 					IsEmptyLine( *pNxtNd ) ||
2233 					IsNoAlphaLine( *pNxtNd );
2234 	}
2235 	else
2236 		bEmptyLine = sal_True;		// am Dokument Anfang
2237 
2238 	bEnde = sal_False;
2239 
2240 	// setze die Werte fuer die Prozent-Anzeige
2241 	nEndNdIdx = aEndNdIdx.GetIndex();
2242 
2243 	if( !aFlags.bAFmtByInput )
2244 		::StartProgress( STR_STATSTR_AUTOFORMAT, aNdIdx.GetIndex(),
2245 						 nEndNdIdx = aEndNdIdx.GetIndex(),
2246 						 pDoc->GetDocShell() );
2247 
2248 	RedlineMode_t eRedlMode = pDoc->GetRedlineMode(), eOldMode = eRedlMode;
2249 	if( aFlags.bWithRedlining )
2250 	{
2251 		pDoc->SetAutoFmtRedline( sal_True );
2252 		eRedlMode = (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT);
2253 	}
2254 	else
2255 	  eRedlMode = (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_IGNORE);
2256 	pDoc->SetRedlineMode( eRedlMode );
2257 
2258     // save undo state (might be turned off)
2259     bool const bUndoState = pDoc->GetIDocumentUndoRedo().DoesUndo();
2260 
2261 	// wenn mehrere Zeilen, dann erstmal nicht mit
2262 	// dem nachfolgenden Absatz zusammenfassen.
2263 	bMoreLines = sal_False;
2264 
2265 	nLastCalcHeadLvl = nLastCalcEnumLvl = 0;
2266 	nLastHeadLvl = nLastEnumLvl = USHRT_MAX;
2267     sal_uInt16 nLevel = 0;
2268     sal_uInt16 nDigitLvl = 0;
2269 
2270 	// defaulten
2271 	SwTxtFrmInfo aFInfo( 0 );
2272 
2273 	// das ist unser Automat fuer die Auto-Formatierung
2274 	eStat = READ_NEXT_PARA;
2275 	while( !bEnde )
2276 	{
2277 		switch( eStat )
2278 		{
2279 		case READ_NEXT_PARA:
2280 			{
2281 				GoNextPara();
2282 				eStat = bEnde ? IS_ENDE : TST_EMPTY_LINE;
2283 			}
2284 			break;
2285 
2286 		case TST_EMPTY_LINE:
2287 			if( IsEmptyLine( *pAktTxtNd ) )
2288 			{
2289 				if( aFlags.bDelEmptyNode && !HasObjects( *pAktTxtNd ) )
2290 				{
2291 					bEmptyLine = sal_True;
2292 					sal_uLong nOldCnt = pDoc->GetNodes().Count();
2293 					DelEmptyLine();
2294 					// wurde wiklich ein Node geloescht ?
2295 					if( nOldCnt != pDoc->GetNodes().Count() )
2296 						aNdIdx--;		// nicht den naechsten Absatz ueberspringen
2297 				}
2298 				eStat = READ_NEXT_PARA;
2299 			}
2300 			else
2301 				eStat = TST_ALPHA_LINE;
2302 			break;
2303 
2304 		case TST_ALPHA_LINE:
2305 			if( IsNoAlphaLine( *pAktTxtNd ))
2306 			{
2307 				// erkenne eine Tabellendefinition +---+---+
2308 				if( aFlags.bAFmtByInput && aFlags.bCreateTable && DoTable() )
2309 				{
2310 					//JP 30.09.96: das DoTable() verlaesst sich auf das
2311 					//				Pop und Move - Crsr nach dem AutoFormat!
2312 					pEdShell->Pop( sal_False );
2313 					*pEdShell->GetCrsr() = aDelPam;
2314 					pEdShell->Push();
2315 
2316 					eStat = IS_ENDE;
2317 					break;
2318 				}
2319 
2320 				// dann teste mal auf 3 "---" oder "===". In dem Fall
2321 				// soll der vorherige Absatz unterstrichen und dieser
2322 				// geloescht werden!
2323 				if( !DoUnderline() && bReplaceStyles )
2324 				{
2325 					SetColl( RES_POOLCOLL_STANDARD, sal_True );
2326 					bEmptyLine = sal_True;
2327 				}
2328 				eStat = READ_NEXT_PARA;
2329 			}
2330 			else
2331 				eStat = GET_ALL_INFO;
2332 			break;
2333 
2334 		case GET_ALL_INFO:
2335 			{
2336 				if( pAktTxtNd->GetNumRule() )
2337 				{
2338 					// in Numerierung nichts machen, zum naechsten
2339 					bEmptyLine = sal_False;
2340 					eStat = READ_NEXT_PARA;
2341 					// loesche alle Blanks am Anfang/Ende
2342 					// und alle mitten drin
2343 					//JP 29.04.98: erstmal nur alle "mitten drin".
2344 					DelMoreLinesBlanks( sal_False );
2345 					break;
2346 				}
2347 
2348 				aFInfo.SetFrm( pAktTxtFrm );
2349 
2350 				// erstmal: wurden schon mal entsprechende Vorlagen
2351 				//			vergeben, so behalte die bei, gehe zum
2352 				//			naechsten Node.
2353 				sal_uInt16 nPoolId = pAktTxtNd->GetTxtColl()->GetPoolFmtId();
2354 				if( IsPoolUserFmt( nPoolId )
2355 						? !aFlags.bChgUserColl
2356 						: ( RES_POOLCOLL_STANDARD != nPoolId &&
2357 						   ( !aFlags.bAFmtByInput ||
2358 							(RES_POOLCOLL_TEXT_MOVE != nPoolId &&
2359 							 RES_POOLCOLL_TEXT != nPoolId )) ))
2360 				{
2361 					eStat = HAS_FMTCOLL;
2362 					break;
2363 				}
2364 
2365 				// teste auf Harte oder aus Vorlagen gesetzte LRSpaces
2366 				if( IsPoolUserFmt( nPoolId ) ||
2367 					RES_POOLCOLL_STANDARD == nPoolId )
2368 				{
2369 					short nSz;
2370 					SvxLRSpaceItem* pLRSpace;
2371 					if( SFX_ITEM_SET == pAktTxtNd->GetSwAttrSet().
2372 						GetItemState( RES_LR_SPACE, sal_True,
2373 										(const SfxPoolItem**)&pLRSpace ) &&
2374 						( 0 != (nSz = pLRSpace->GetTxtFirstLineOfst()) ||
2375 							0 != pLRSpace->GetTxtLeft() ) )
2376 					{
2377 						// Ausnahme: Numerierun/Aufzaehlung kann mit Einzug
2378 						//		existieren!!
2379 						if( IsEnumericChar( *pAktTxtNd ))
2380 						{
2381 							nLevel = CalcLevel( *pAktTxtNd, &nDigitLvl );
2382 							if( nLevel >= MAXLEVEL )
2383 								nLevel = MAXLEVEL-1;
2384 							BuildEnum( nLevel, nDigitLvl );
2385 							eStat = READ_NEXT_PARA;
2386 							break;
2387 						}
2388 
2389 
2390 						// nie zusammenfassen, so belassen
2391 						// (Opt. vielleicht als Ausnahmen nur Einzug)
2392 						bMoreLines = sal_True;
2393 
2394 						if( bReplaceStyles )
2395 						{
2396 							// dann setze doch eine unserer Vorlagen
2397 							if( 0 < nSz )			// positiver 1. Zeileneinzug
2398 								BuildIndent();
2399 							else if( 0 > nSz )		// negativer 1. Zeileneinzug
2400 								BuildNegIndent( aFInfo.GetLineStart() );
2401 							else if( pLRSpace->GetTxtLeft() )	// ist ein Einzug
2402 								BuildTextIndent();
2403 						}
2404 						eStat = READ_NEXT_PARA;
2405 						break;
2406 					}
2407 				}
2408 
2409 				nLevel = CalcLevel( *pAktTxtNd, &nDigitLvl );
2410 				bMoreLines = !IsOneLine( *pAktTxtNd );
2411 				pNxtNd = GetNextNode();
2412 				if( pNxtNd )
2413 				{
2414 					bNxtEmpty = IsEmptyLine( *pNxtNd );
2415 					bNxtAlpha = IsNoAlphaLine( *pNxtNd );
2416 					nNxtLevel = CalcLevel( *pNxtNd );
2417 
2418 					if( !bEmptyLine && HasBreakAttr( *pAktTxtNd ) )
2419 						bEmptyLine = sal_True;
2420 					if( !bNxtEmpty && HasBreakAttr( *pNxtNd ) )
2421 						bNxtEmpty = sal_True;
2422 
2423 					// fuer z.B. selbst definierte Einzuege oder
2424 					// rechts/zentierte Ausrichtung
2425 //					if( !nLevel && 0 != aFInfo.GetLineStart() )
2426 //						nLevel = 1;
2427 				}
2428 				else
2429 				{
2430 					bNxtEmpty = sal_False; // sal_True;
2431 					bNxtAlpha = sal_False;
2432 					nNxtLevel = 0;
2433 				}
2434 				eStat = !bMoreLines ? IS_ONE_LINE : TST_ENUMERIC;
2435 			}
2436 			break;
2437 
2438 		case IS_ONE_LINE:
2439 			{
2440 				eStat = TST_ENUMERIC;
2441 				if( !bReplaceStyles )
2442 					break;
2443 
2444 				String sClrStr( pAktTxtNd->GetTxt() );
2445 
2446 				if( !DelLeadingBlanks( sClrStr ).Len() )
2447 				{
2448 					bEmptyLine = sal_True;
2449 					eStat = READ_NEXT_PARA;
2450 					break;		// naechsten Absatz lesen
2451 				}
2452 
2453 				// Teste auf Ueberschrift
2454 				if( !bEmptyLine || !IsFirstCharCapital( *pAktTxtNd ) ||
2455 					IsBlanksInString( *pAktTxtNd ) )
2456 					break;
2457 
2458 				bEmptyLine = sal_False;
2459 				String sEndClrStr( sClrStr );
2460 				xub_StrLen nLen = DelTrailingBlanks( sEndClrStr ).Len();
2461 
2462 				// nicht, dann teste auf Ueberschrift
2463 				if( ':' == sEndClrStr.GetChar( nLen - 1 ) )
2464 				{
2465 //---------------------------------------------------------------------------
2466 // Wie ist denn nun die Bedingung fuer die Ueberschrift auf Ebene 3 ??
2467 // Zur Zeit: generell wenn am Ende ein ':' ist.
2468 //
2469 //					if( bNxtEmpty || bNxtAlpha )
2470 //						!IsEnumericChar( *pNxtNd ) )
2471 //---------------------------------------------------------------------------
2472 					{
2473 						BuildHeadLine( 2 );
2474 						eStat = READ_NEXT_PARA;
2475 						break;
2476 					}
2477 				}
2478 				else if( 256 <= sEndClrStr.GetChar( nLen-1 ) ||
2479 						 !strchr( ",.;", sEndClrStr.GetChar( nLen-1 )) )
2480 				{
2481 					if( bNxtEmpty || bNxtAlpha
2482 						|| ( pNxtNd && IsEnumericChar( *pNxtNd ))
2483 
2484 //---------------------------------------------------------------------------
2485 // ist zum Verwechseln mit neg. Einzug !!
2486 						/*|| nLevel < nNxtLevel*/
2487 //---------------------------------------------------------------------------
2488 
2489 						)
2490 					{
2491 						// wurde Level vom Text vorgegeben ?
2492 //						if( USHRT_MAX != nDigitLvl )
2493 //							nLevel = nDigitLvl;
2494 
2495 						// eine Ebene runter ?
2496 						if( nLevel >= MAXLEVEL )
2497 							nLevel = MAXLEVEL-1;
2498 
2499 						if( USHRT_MAX == nLastHeadLvl )
2500 							nLastHeadLvl = 0;
2501 						else if( nLastCalcHeadLvl < nLevel )
2502 						{
2503 							if( nLastHeadLvl+1 < MAXLEVEL )
2504 								++nLastHeadLvl;
2505 						}
2506 						// eine Ebene hoch ?
2507 						else if( nLastCalcHeadLvl > nLevel )
2508 						{
2509 							if( nLastHeadLvl )
2510 								--nLastHeadLvl;
2511 						}
2512 						nLastCalcHeadLvl = nLevel;
2513 
2514 						if( aFlags.bAFmtByInput )
2515 							BuildHeadLine( nLevel );
2516 						else
2517 							BuildHeadLine( nLastHeadLvl );
2518 						eStat = READ_NEXT_PARA;
2519 						break;
2520 					}
2521 				}
2522 			}
2523 			break;
2524 
2525 		case TST_ENUMERIC:
2526 			{
2527 				bEmptyLine = sal_False;
2528 				if( IsEnumericChar( *pAktTxtNd ))
2529 				{
2530 					if( nLevel >= MAXLEVEL )
2531 						nLevel = MAXLEVEL-1;
2532 					BuildEnum( nLevel, nDigitLvl );
2533 					eStat = READ_NEXT_PARA;
2534 				}
2535 //JP 25.03.96: Vorlagen fuer Einzug zulassen
2536 //				else if( aFlags.bAFmtByInput )
2537 //					eStat = READ_NEXT_PARA;
2538 				else if( bReplaceStyles )
2539 					eStat = nLevel ? TST_IDENT : TST_NEG_IDENT;
2540 				else
2541 					eStat = READ_NEXT_PARA;
2542 			}
2543 			break;
2544 
2545 		case TST_IDENT:
2546 			// Spaces am Anfang, dann teste doch mal auf Einzuege
2547 			if( bMoreLines && nLevel )
2548 			{
2549 				SwTwips nSz = aFInfo.GetFirstIndent();
2550 				if( 0 < nSz )			// positiver 1. Zeileneinzug
2551 					BuildIndent();
2552 				else if( 0 > nSz )		// negativer 1. Zeileneinzug
2553 					BuildNegIndent( aFInfo.GetLineStart() );
2554 				else					// ist ein Einzug
2555 					BuildTextIndent();
2556 				eStat = READ_NEXT_PARA;
2557 			}
2558 			else if( nLevel && pNxtNd && !bEnde &&
2559 					 !bNxtEmpty && !bNxtAlpha && !nNxtLevel &&
2560 					 !IsEnumericChar( *pNxtNd ) )
2561 			{
2562 				// ist ein Einzug
2563 				BuildIndent();
2564 				eStat = READ_NEXT_PARA;
2565 			}
2566 			else
2567 				eStat = TST_TXT_BODY;
2568 			break;
2569 
2570 		case TST_NEG_IDENT:
2571 			// keine Spaces am Anfang, dann teste doch mal auf neg. Einzuege
2572 			{
2573 				if( bMoreLines && !nLevel )
2574 				{
2575 					SwTwips nSz = aFInfo.GetFirstIndent();
2576 					if( 0 < nSz )			// positiver 1. Zeileneinzug
2577 						BuildIndent();
2578 					else if( 0 > nSz )		// negativer 1. Zeileneinzug
2579 						BuildNegIndent( aFInfo.GetLineStart() );
2580 					else					// ist ein kein Einzug
2581 						BuildText();
2582 					eStat = READ_NEXT_PARA;
2583 				}
2584 				else if( !nLevel && pNxtNd && !bEnde &&
2585 						 !bNxtEmpty && !bNxtAlpha && nNxtLevel &&
2586 						 !IsEnumericChar( *pNxtNd ) )
2587 				{
2588 					// ist ein neg. Einzug
2589 					BuildNegIndent( aFInfo.GetLineStart() );
2590 					eStat = READ_NEXT_PARA;
2591 				}
2592 				else
2593 					eStat = TST_TXT_BODY;
2594 			}
2595 			break;
2596 
2597 		case TST_TXT_BODY:
2598 			{
2599 				if( bMoreLines )
2600 				{
2601 					SwTwips nSz = aFInfo.GetFirstIndent();
2602 					if( 0 < nSz )			// positiver 1. Zeileneinzug
2603 						BuildIndent();
2604 					else if( 0 > nSz )		// negativer 1. Zeileneinzug
2605 						BuildNegIndent( aFInfo.GetLineStart() );
2606 					else if( nLevel )		// ist ein Einzug
2607 						BuildTextIndent();
2608 					else
2609 						BuildText();
2610 				}
2611 				else if( nLevel )
2612 					BuildTextIndent();
2613 				else
2614 					BuildText();
2615 				eStat = READ_NEXT_PARA;
2616 			}
2617 			break;
2618 
2619 		case HAS_FMTCOLL:
2620 			{
2621 				// erstmal: wurden schon mal entsprechende Vorlagen
2622 				//			vergeben, so behalte die bei, gehe zum
2623 				//			naechsten Node.
2624 				bEmptyLine = sal_False;
2625 				eStat = READ_NEXT_PARA;
2626 				// loesche alle Blanks am Anfang/Ende
2627 				// und alle mitten drin
2628 				//JP 29.04.98: erstmal nur alle "mitten drin".
2629 				DelMoreLinesBlanks( sal_False );
2630 
2631 				// behandel die harte Attributierung
2632                 if( pAktTxtNd->HasSwAttrSet() )
2633 				{
2634 					short nSz;
2635 					SvxLRSpaceItem* pLRSpace;
2636 					if( bReplaceStyles &&
2637                         SFX_ITEM_SET == pAktTxtNd->GetSwAttrSet().
2638 						GetItemState( RES_LR_SPACE, sal_False,
2639 										(const SfxPoolItem**)&pLRSpace ) &&
2640 						( 0 != (nSz = pLRSpace->GetTxtFirstLineOfst()) ||
2641 							0 != pLRSpace->GetTxtLeft() ) )
2642 					{
2643 						// dann setze doch eine unserer Vorlagen
2644 						if( 0 < nSz )			// positiver 1. Zeileneinzug
2645 							BuildIndent();
2646 						else if( 0 > nSz )		// negativer 1. Zeileneinzug
2647 						{
2648 							BuildNegIndent( aFInfo.GetLineStart() );
2649 						}
2650 						else if( pLRSpace->GetTxtLeft() )	// ist ein Einzug
2651 							BuildTextIndent();
2652 						else
2653 							BuildText();
2654 					}
2655 				}
2656 			}
2657 			break;
2658 
2659 		case IS_ENDE:
2660 			bEnde = sal_True;
2661 			break;
2662 		}
2663 	}
2664 
2665 	if( aFlags.bWithRedlining )
2666 		pDoc->SetAutoFmtRedline( sal_False );
2667 	pDoc->SetRedlineMode( eOldMode );
2668 
2669     // restore undo (in case it has been changed)
2670     pDoc->GetIDocumentUndoRedo().DoUndo(bUndoState);
2671 
2672 	// Prozent-Anzeige wieder abschalten
2673 	if( !aFlags.bAFmtByInput )
2674 		::EndProgress( pDoc->GetDocShell() );
2675 }
2676 
2677 void SwEditShell::AutoFormat( const SvxSwAutoFmtFlags* pAFlags )
2678 {
2679 	SwWait* pWait = 0;
2680 
2681 	SET_CURR_SHELL( this );
2682 	StartAllAction();
2683 	StartUndo( UNDO_AUTOFORMAT );
2684 
2685 	SvxSwAutoFmtFlags aAFFlags;		// erst mal default - Werte
2686 	if( pAFlags )					// oder doch angegeben ??
2687 	{
2688 		aAFFlags = *pAFlags;
2689 		if( !aAFFlags.bAFmtByInput )
2690 			pWait = new SwWait( *GetDoc()->GetDocShell(), sal_True );
2691 	}
2692 
2693 	SwPaM* pCrsr = GetCrsr();
2694 	// es gibt mehr als einen oder ist eine Selektion offen
2695 	if( pCrsr->GetNext() != pCrsr || pCrsr->HasMark() )
2696 	{
2697 		FOREACHPAM_START(this)
2698 			if( PCURCRSR->HasMark() )
2699 			{
2700 				SwAutoFormat aFmt( this, aAFFlags, &PCURCRSR->Start()->nNode,
2701 									 &PCURCRSR->End()->nNode );
2702 			}
2703 		FOREACHPAM_END()
2704 	}
2705 	else
2706 	{
2707 		SwAutoFormat aFmt( this, aAFFlags );
2708 	}
2709 
2710 	EndUndo( UNDO_AUTOFORMAT );
2711 	EndAllAction();
2712 
2713 	delete pWait;
2714 }
2715 
2716 
2717 void SwEditShell::AutoFmtBySplitNode()
2718 {
2719 	SET_CURR_SHELL( this );
2720 	SwPaM* pCrsr = GetCrsr();
2721 	if( pCrsr->GetNext() == pCrsr && pCrsr->Move( fnMoveBackward, fnGoNode ) )
2722 	{
2723 		StartAllAction();
2724 		StartUndo( UNDO_AUTOFORMAT );
2725 
2726 		sal_Bool bRange = sal_False;
2727 		pCrsr->SetMark();
2728 		SwIndex* pCntnt = &pCrsr->GetMark()->nContent;
2729 		if( pCntnt->GetIndex() )
2730 		{
2731 			*pCntnt = 0;
2732 			bRange = sal_True;
2733 		}
2734 		else
2735 		{
2736 			// dann einen Node zurueckspringen
2737 			SwNodeIndex aNdIdx( pCrsr->GetMark()->nNode, -1 );
2738 			SwTxtNode* pTxtNd = aNdIdx.GetNode().GetTxtNode();
2739 			if( pTxtNd && pTxtNd->GetTxt().Len() )
2740 			{
2741 				pCntnt->Assign( pTxtNd, 0 );
2742 				pCrsr->GetMark()->nNode = aNdIdx;
2743 				bRange = sal_True;
2744 			}
2745 		}
2746 
2747 		if( bRange )
2748 		{
2749 			Push();		// Cursor sichern
2750 
2751 			SvxSwAutoFmtFlags aAFFlags = *GetAutoFmtFlags();		// erst mal default - Werte
2752 
2753 			SwAutoFormat aFmt( this, aAFFlags, &pCrsr->GetMark()->nNode,
2754 									&pCrsr->GetPoint()->nNode );
2755 
2756 			//JP 30.09.96: das DoTable() verlaesst sich auf das PopCrsr
2757 			//				und MoveCrsr!
2758 			Pop( sal_False );
2759 			pCrsr = GetCrsr();
2760 		}
2761 		pCrsr->DeleteMark();
2762 		pCrsr->Move( fnMoveForward, fnGoNode );
2763 
2764 		EndUndo( UNDO_AUTOFORMAT );
2765 		EndAllAction();
2766 	}
2767 }
2768 
2769 SvxSwAutoFmtFlags* SwEditShell::GetAutoFmtFlags()
2770 {
2771 	if (!pAutoFmtFlags)
2772 		pAutoFmtFlags = new SvxSwAutoFmtFlags;
2773 
2774 	return pAutoFmtFlags;
2775 }
2776 
2777 void SwEditShell::SetAutoFmtFlags(SvxSwAutoFmtFlags * pFlags)
2778 {
2779 	SvxSwAutoFmtFlags* pEditFlags = GetAutoFmtFlags();
2780 
2781 	pEditFlags->bSetNumRule		= pFlags->bSetNumRule;
2782 	pEditFlags->bChgEnumNum		= pFlags->bChgEnumNum;
2783 	pEditFlags->bSetBorder		= pFlags->bSetBorder;
2784 	pEditFlags->bCreateTable	= pFlags->bCreateTable;
2785 	pEditFlags->bReplaceStyles	= pFlags->bReplaceStyles;
2786 	pEditFlags->bAFmtByInpDelSpacesAtSttEnd =
2787 									pFlags->bAFmtByInpDelSpacesAtSttEnd;
2788 	pEditFlags->bAFmtByInpDelSpacesBetweenLines =
2789 									pFlags->bAFmtByInpDelSpacesBetweenLines;
2790 
2791 	//JP 15.12.98: BulletZeichen und Font in die "normalen" kopieren,
2792 	//			weil beim Autoformat nur mit diesen gearbeitet wird!
2793 	pEditFlags->cBullet				= pFlags->cByInputBullet;
2794 	pEditFlags->aBulletFont			= pFlags->aByInputBulletFont;
2795 	pEditFlags->cByInputBullet		= pFlags->cByInputBullet;
2796 	pEditFlags->aByInputBulletFont	= pFlags->aByInputBulletFont;
2797 }
2798 
2799