xref: /AOO41X/main/sw/source/core/edit/autofmt.cxx (revision 8ef2f12b1aeba1404ab3c221e6e26281826cc4fc)
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