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