Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <ctype.h>
21 : #include <hintids.hxx>
22 :
23 : #include <unotools/charclass.hxx>
24 :
25 : #include <vcl/msgbox.hxx>
26 :
27 : #include <editeng/boxitem.hxx>
28 : #include <editeng/lrspitem.hxx>
29 : #include <editeng/formatbreakitem.hxx>
30 : #include <editeng/adjustitem.hxx>
31 : #include <editeng/tstpitem.hxx>
32 : #include <editeng/fontitem.hxx>
33 : #include <editeng/langitem.hxx>
34 : #include <editeng/charsetcoloritem.hxx>
35 : #include <editeng/unolingu.hxx>
36 : #include <editeng/acorrcfg.hxx>
37 :
38 : #include <swwait.hxx>
39 : #include <fmtpdsc.hxx>
40 : #include <fmtanchr.hxx>
41 : #include <doc.hxx>
42 : #include <IDocumentUndoRedo.hxx>
43 : #include <docary.hxx>
44 : #include <editsh.hxx>
45 : #include <index.hxx>
46 : #include <pam.hxx>
47 : #include <edimp.hxx>
48 : #include <fesh.hxx>
49 : #include <swundo.hxx>
50 : #include <poolfmt.hxx>
51 : #include <ndtxt.hxx>
52 : #include <txtfrm.hxx>
53 : #include <frminf.hxx>
54 : #include <pagedesc.hxx>
55 : #include <paratr.hxx>
56 : #include <swtable.hxx>
57 : #include <acorrect.hxx>
58 : #include <shellres.hxx>
59 : #include <section.hxx>
60 : #include <frmatr.hxx>
61 : #include <charatr.hxx>
62 : #include <mdiexp.hxx>
63 : #include <statstr.hrc>
64 : #include <comcore.hrc>
65 : #include <numrule.hxx>
66 :
67 : #include <boost/scoped_ptr.hpp>
68 :
69 : using namespace ::com::sun::star;
70 :
71 : //JP 16.12.99: definition:
72 : // from pos cPosEnDash to cPosEmDash all chars changed to endashes,
73 : // from pos cPosEmDash to cPosEnd all chars changed to emdashes
74 : // all other chars are changed to the user configuration
75 :
76 : const sal_Unicode pBulletChar[6] = { '+', '*', '-', 0x2013, 0x2014, 0 };
77 : const int cnPosEnDash = 2, cnPosEmDash = 4;
78 :
79 : const sal_Unicode cStarSymbolEnDash = 0x2013;
80 : const sal_Unicode cStarSymbolEmDash = 0x2014;
81 :
82 : SvxSwAutoFmtFlags* SwEditShell::pAutoFmtFlags = 0;
83 :
84 : // Number of num-/bullet-paragraph templates. MAXLEVEL will soon be raised
85 : // to x, but not the number of templates. (Artifact from <= 4.0)
86 : const sal_uInt16 cnNumBullColls = 4;
87 :
88 0 : class SwAutoFormat
89 : {
90 : SvxSwAutoFmtFlags m_aFlags;
91 : SwPaM m_aDelPam; // a Pam that can be used
92 : SwNodeIndex m_aNdIdx; // the index on the current TextNode
93 : SwNodeIndex m_aEndNdIdx; // index on the end of the area
94 :
95 : SwEditShell* m_pEditShell;
96 : SwDoc* m_pDoc;
97 : SwTxtNode* m_pCurTxtNd; // the current TextNode
98 : SwTxtFrm* m_pCurTxtFrm; // frame of the current TextNode
99 : sal_uLong m_nEndNdIdx; // for the percentage-display
100 : mutable boost::scoped_ptr<CharClass> m_pCharClass; // Character classification
101 : mutable LanguageType m_eCharClassLang;
102 :
103 : sal_uInt16 m_nLastHeadLvl, m_nLastCalcHeadLvl;
104 : sal_uInt16 m_nRedlAutoFmtSeqId;
105 :
106 : enum
107 : {
108 : NONE = 0,
109 : DELIM = 1,
110 : DIGIT = 2,
111 : CHG = 4,
112 : LOWER_ALPHA = 8,
113 : UPPER_ALPHA = 16,
114 : LOWER_ROMAN = 32,
115 : UPPER_ROMAN = 64,
116 : NO_DELIM = (DIGIT|LOWER_ALPHA|UPPER_ALPHA|LOWER_ROMAN|UPPER_ROMAN)
117 : };
118 :
119 : enum Format_Status
120 : {
121 : READ_NEXT_PARA,
122 : TST_EMPTY_LINE,
123 : TST_ALPHA_LINE,
124 : GET_ALL_INFO,
125 : IS_ONE_LINE,
126 : TST_ENUMERIC,
127 : TST_IDENT,
128 : TST_NEG_IDENT,
129 : TST_TXT_BODY,
130 : HAS_FMTCOLL,
131 : IS_END
132 : } m_eStat;
133 :
134 : bool m_bEnd : 1;
135 : bool m_bEmptyLine : 1;
136 : bool m_bMoreLines : 1;
137 :
138 : // ------------- private methods -----------------------------
139 0 : CharClass& GetCharClass( LanguageType eLang ) const
140 : {
141 0 : if( !m_pCharClass || eLang != m_eCharClassLang )
142 : {
143 0 : m_pCharClass.reset( new CharClass( LanguageTag( eLang ) ) );
144 0 : m_eCharClassLang = eLang;
145 : }
146 0 : return *m_pCharClass;
147 : }
148 :
149 0 : bool IsSpace( const sal_Unicode c ) const
150 0 : { return (' ' == c || '\t' == c || 0x0a == c|| 0x3000 == c /* Jap. space */); }
151 :
152 : void SetColl( sal_uInt16 nId, bool bHdLineOrText = false );
153 : OUString GoNextPara();
154 : bool HasObjects( const SwNode& rNd );
155 :
156 : // TxtNode methods
157 : const SwTxtNode* GetNextNode() const;
158 0 : bool IsEmptyLine( const SwTxtNode& rNd ) const
159 0 : { return rNd.GetTxt().isEmpty() ||
160 0 : rNd.GetTxt().getLength() == GetLeadingBlanks( rNd.GetTxt() ); }
161 :
162 : sal_Bool IsOneLine( const SwTxtNode& ) const;
163 : sal_Bool IsFastFullLine( const SwTxtNode& ) const;
164 : sal_Bool IsNoAlphaLine( const SwTxtNode&) const;
165 : sal_Bool IsEnumericChar( const SwTxtNode&) const;
166 : sal_Bool IsBlanksInString( const SwTxtNode&) const;
167 : sal_uInt16 CalcLevel( const SwTxtNode&, sal_uInt16 *pDigitLvl = 0 ) const;
168 : sal_Int32 GetBigIndent( sal_Int32& rAktSpacePos ) const;
169 :
170 : OUString DelLeadingBlanks(const OUString& rStr) const;
171 : OUString& DelTrailingBlanks( OUString& rStr ) const;
172 : sal_Int32 GetLeadingBlanks( const OUString& rStr ) const;
173 : sal_Int32 GetTrailingBlanks( const OUString& rStr ) const;
174 :
175 : bool IsFirstCharCapital( const SwTxtNode& rNd ) const;
176 : sal_uInt16 GetDigitLevel( const SwTxtNode& rTxtNd, sal_Int32& rPos,
177 : OUString* pPrefix = 0, OUString* pPostfix = 0,
178 : OUString* pNumTypes = 0 ) const;
179 : /// get the FORMATED TextFrame
180 : SwTxtFrm* GetFrm( const SwTxtNode& rTxtNd ) const;
181 :
182 : void BuildIndent();
183 : void BuildText();
184 : void BuildTextIndent();
185 : void BuildEnum( sal_uInt16 nLvl, sal_uInt16 nDigitLevel );
186 : void BuildNegIndent( SwTwips nSpaces );
187 : void BuildHeadLine( sal_uInt16 nLvl );
188 :
189 : bool HasSelBlanks( SwPaM& rPam ) const;
190 : bool HasBreakAttr( const SwTxtNode& ) const;
191 : void DeleteSel( SwPaM& rPam );
192 : bool DeleteCurNxtPara( const OUString& rNxtPara );
193 : /// delete in the node start and/or end
194 : void DeleteCurrentParagraph( bool bStart = true, bool nEnd = true );
195 : void DelEmptyLine( bool bTstNextPara = true );
196 : /// when using multiline paragraphs delete the "left" and/or
197 : /// "right" margins
198 : void DelMoreLinesBlanks( bool bWithLineBreaks = false );
199 : /// delete the previous paragraph
200 : void DelPrevPara();
201 : /// execute AutoCorrect on current TextNode
202 : void AutoCorrect( sal_Int32 nSttPos = 0 );
203 :
204 0 : bool CanJoin( const SwTxtNode* pTxtNd ) const
205 : {
206 0 : return !m_bEnd && pTxtNd &&
207 0 : !IsEmptyLine( *pTxtNd ) &&
208 0 : !IsNoAlphaLine( *pTxtNd) &&
209 0 : !IsEnumericChar( *pTxtNd ) &&
210 0 : ((COMPLETE_STRING - 50 - pTxtNd->GetTxt().getLength()) >
211 0 : m_pCurTxtNd->GetTxt().getLength()) &&
212 0 : !HasBreakAttr( *pTxtNd );
213 : }
214 :
215 : /// is a dot at the end ??
216 : bool IsSentenceAtEnd( const SwTxtNode& rTxtNd ) const;
217 :
218 : bool DoUnderline();
219 : bool DoTable();
220 :
221 : void _SetRedlineTxt( sal_uInt16 nId );
222 0 : bool SetRedlineTxt( sal_uInt16 nId )
223 0 : { if( m_aFlags.bWithRedlining ) _SetRedlineTxt( nId ); return true; }
224 0 : bool ClearRedlineTxt()
225 0 : { if( m_aFlags.bWithRedlining ) m_pDoc->SetAutoFmtRedlineComment(0); return true; }
226 :
227 : public:
228 : SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFmtFlags& rFlags,
229 : SwNodeIndex* pSttNd = 0, SwNodeIndex* pEndNd = 0 );
230 : };
231 :
232 0 : const sal_Unicode* StrChr( const sal_Unicode* pSrc, sal_Unicode c )
233 : {
234 0 : while( *pSrc && *pSrc != c )
235 0 : ++pSrc;
236 0 : return *pSrc ? pSrc : 0;
237 : }
238 :
239 0 : SwTxtFrm* SwAutoFormat::GetFrm( const SwTxtNode& rTxtNd ) const
240 : {
241 : // get the Frame
242 0 : const SwCntntFrm *pFrm = rTxtNd.getLayoutFrm( m_pEditShell->GetLayout() );
243 : OSL_ENSURE( pFrm, "For Autoformat a Layout is needed" );
244 0 : if( m_aFlags.bAFmtByInput && !pFrm->IsValid() )
245 : {
246 0 : SwRect aTmpFrm( pFrm->Frm() );
247 0 : SwRect aTmpPrt( pFrm->Prt() );
248 0 : pFrm->Calc();
249 0 : if( pFrm->Frm() != aTmpFrm || pFrm->Prt() != aTmpPrt ||
250 0 : ( pFrm->IsTxtFrm() && !((SwTxtFrm*)pFrm)->Paint().IsEmpty() ) )
251 0 : pFrm->SetCompletePaint();
252 : }
253 0 : return ((SwTxtFrm*)pFrm)->GetFormatted();
254 : }
255 :
256 0 : void SwAutoFormat::_SetRedlineTxt( sal_uInt16 nActionId )
257 : {
258 0 : OUString sTxt;
259 0 : sal_uInt16 nSeqNo = 0;
260 0 : if( STR_AUTOFMTREDL_END > nActionId )
261 : {
262 0 : sTxt = SwViewShell::GetShellRes()->GetAutoFmtNameLst()[ nActionId ];
263 0 : switch( nActionId )
264 : {
265 : case STR_AUTOFMTREDL_SET_NUMBULET:
266 : case STR_AUTOFMTREDL_DEL_MORELINES:
267 :
268 : // AutoCorrect actions
269 : case STR_AUTOFMTREDL_USE_REPLACE:
270 : case STR_AUTOFMTREDL_CPTL_STT_WORD:
271 : case STR_AUTOFMTREDL_CPTL_STT_SENT:
272 : case STR_AUTOFMTREDL_TYPO:
273 : case STR_AUTOFMTREDL_UNDER:
274 : case STR_AUTOFMTREDL_BOLD:
275 : case STR_AUTOFMTREDL_FRACTION:
276 : case STR_AUTOFMTREDL_DASH:
277 : case STR_AUTOFMTREDL_ORDINAL:
278 : case STR_AUTOFMTREDL_NON_BREAK_SPACE:
279 0 : nSeqNo = ++m_nRedlAutoFmtSeqId;
280 0 : break;
281 : }
282 : }
283 : #if OSL_DEBUG_LEVEL > 0
284 : else
285 : sTxt = "Action text is missing";
286 : #endif
287 :
288 0 : m_pDoc->SetAutoFmtRedlineComment( &sTxt, nSeqNo );
289 0 : }
290 :
291 0 : OUString SwAutoFormat::GoNextPara()
292 : {
293 0 : SwNode* pNewNd = 0;
294 0 : do {
295 : // has to be checked twice before and after incrementation
296 0 : if( m_aNdIdx.GetIndex() >= m_aEndNdIdx.GetIndex() )
297 : {
298 0 : m_bEnd = true;
299 0 : return OUString();
300 : }
301 :
302 0 : m_aNdIdx++;
303 0 : if( m_aNdIdx.GetIndex() >= m_aEndNdIdx.GetIndex() )
304 : {
305 0 : m_bEnd = true;
306 0 : return OUString();
307 : }
308 : else
309 0 : pNewNd = &m_aNdIdx.GetNode();
310 :
311 : // not a TextNode ->
312 : // TableNode : skip table
313 : // NoTxtNode : skip nodes
314 : // EndNode : at the end, terminate
315 0 : if( pNewNd->IsEndNode() )
316 : {
317 0 : m_bEnd = true;
318 0 : return OUString();
319 : }
320 0 : else if( pNewNd->IsTableNode() )
321 0 : m_aNdIdx = *pNewNd->EndOfSectionNode();
322 0 : else if( pNewNd->IsSectionNode() )
323 : {
324 0 : const SwSection& rSect = pNewNd->GetSectionNode()->GetSection();
325 0 : if( rSect.IsHiddenFlag() || rSect.IsProtectFlag() )
326 0 : m_aNdIdx = *pNewNd->EndOfSectionNode();
327 : }
328 0 : } while( !pNewNd->IsTxtNode() );
329 :
330 0 : if( !m_aFlags.bAFmtByInput )
331 0 : ::SetProgressState( m_aNdIdx.GetIndex() + m_nEndNdIdx - m_aEndNdIdx.GetIndex(),
332 0 : m_pDoc->GetDocShell() );
333 :
334 0 : m_pCurTxtNd = (SwTxtNode*)pNewNd;
335 0 : m_pCurTxtFrm = GetFrm( *m_pCurTxtNd );
336 0 : return m_pCurTxtNd->GetTxt();
337 : }
338 :
339 0 : bool SwAutoFormat::HasObjects( const SwNode& rNd )
340 : {
341 : // Is there something bound to the paragraph in the paragraph
342 : // like borders, DrawObjects, ...
343 0 : bool bRet = false;
344 0 : const SwFrmFmts& rFmts = *m_pDoc->GetSpzFrmFmts();
345 0 : for( sal_uInt16 n = 0; n < rFmts.size(); ++n )
346 : {
347 0 : const SwFmtAnchor& rAnchor = rFmts[ n ]->GetAnchor();
348 0 : if ((FLY_AT_PAGE != rAnchor.GetAnchorId()) &&
349 0 : rAnchor.GetCntntAnchor() &&
350 0 : &rAnchor.GetCntntAnchor()->nNode.GetNode() == &rNd )
351 : {
352 0 : bRet = true;
353 0 : break;
354 : }
355 : }
356 0 : return bRet;
357 : }
358 :
359 0 : const SwTxtNode* SwAutoFormat::GetNextNode() const
360 : {
361 0 : if( m_aNdIdx.GetIndex()+1 >= m_aEndNdIdx.GetIndex() )
362 0 : return 0;
363 0 : return m_pDoc->GetNodes()[ m_aNdIdx.GetIndex() + 1 ]->GetTxtNode();
364 : }
365 :
366 0 : sal_Bool SwAutoFormat::IsOneLine( const SwTxtNode& rNd ) const
367 : {
368 0 : SwTxtFrmInfo aFInfo( GetFrm( rNd ) );
369 0 : return aFInfo.IsOneLine();
370 : }
371 :
372 0 : sal_Bool SwAutoFormat::IsFastFullLine( const SwTxtNode& rNd ) const
373 : {
374 0 : sal_Bool bRet = m_aFlags.bRightMargin;
375 0 : if( bRet )
376 : {
377 0 : SwTxtFrmInfo aFInfo( GetFrm( rNd ) );
378 0 : bRet = aFInfo.IsFilled( m_aFlags.nRightMargin );
379 : }
380 0 : return bRet;
381 : }
382 :
383 0 : sal_Bool SwAutoFormat::IsEnumericChar( const SwTxtNode& rNd ) const
384 : {
385 0 : const OUString& rTxt = rNd.GetTxt();
386 0 : sal_Int32 nBlnks = GetLeadingBlanks( rTxt );
387 0 : const sal_Int32 nLen = rTxt.getLength() - nBlnks;
388 0 : if( !nLen )
389 0 : return sal_False;
390 :
391 : // -, +, * separated by blank ??
392 0 : if (2 < nLen && IsSpace(rTxt[nBlnks + 1]))
393 : {
394 0 : if (StrChr(pBulletChar, rTxt[nBlnks]))
395 0 : return sal_True;
396 : // Should there be a symbol font at the position?
397 0 : SwTxtFrmInfo aFInfo( GetFrm( rNd ) );
398 0 : if( aFInfo.IsBullet( nBlnks ))
399 0 : return sal_True;
400 : }
401 :
402 : // 1.) / 1. / 1.1.1 / (1). / (1) / ....
403 0 : return USHRT_MAX != GetDigitLevel( rNd, nBlnks );
404 : }
405 :
406 0 : sal_Bool SwAutoFormat::IsBlanksInString( const SwTxtNode& rNd ) const
407 : {
408 : // Search more than 5 consecutive blanks/tabs in the string.
409 0 : OUString sTmp( DelLeadingBlanks(rNd.GetTxt()) );
410 0 : const sal_Int32 nLen = sTmp.getLength();
411 0 : sal_Int32 nIdx = 0;
412 0 : while (nIdx < nLen)
413 : {
414 : // Skip non-blanks
415 0 : while (nIdx < nLen && !IsSpace(sTmp[nIdx])) ++nIdx;
416 0 : if (nIdx == nLen)
417 0 : return sal_False;
418 : // Then count consecutive blanks
419 0 : const sal_Int32 nFirst = nIdx;
420 0 : while (nIdx < nLen && IsSpace(sTmp[nIdx])) ++nIdx;
421 : // And exit if enough consecutive blanks were found
422 0 : if (nIdx-nFirst > 5)
423 0 : return sal_True;
424 : }
425 0 : return sal_False;
426 : }
427 :
428 0 : sal_uInt16 SwAutoFormat::CalcLevel( const SwTxtNode& rNd, sal_uInt16 *pDigitLvl ) const
429 : {
430 0 : sal_uInt16 nLvl = 0, nBlnk = 0;
431 0 : const OUString& rTxt = rNd.GetTxt();
432 0 : if( pDigitLvl )
433 0 : *pDigitLvl = USHRT_MAX;
434 :
435 0 : if( RES_POOLCOLL_TEXT_MOVE == rNd.GetTxtColl()->GetPoolFmtId() )
436 : {
437 0 : if( m_aFlags.bAFmtByInput )
438 : {
439 0 : nLvl = rNd.GetAutoFmtLvl();
440 0 : ((SwTxtNode&)rNd).SetAutoFmtLvl( 0 );
441 0 : if( nLvl )
442 0 : return nLvl;
443 : }
444 0 : ++nLvl;
445 : }
446 :
447 0 : for (sal_Int32 n = 0, nEnd = rTxt.getLength(); n < nEnd; ++n)
448 : {
449 0 : switch (rTxt[n])
450 : {
451 0 : case ' ': if( 3 == ++nBlnk )
452 0 : ++nLvl, nBlnk = 0;
453 0 : break;
454 0 : case '\t': ++nLvl, nBlnk = 0;
455 0 : break;
456 : default:
457 0 : if( pDigitLvl )
458 : // test 1.) / 1. / 1.1.1 / (1). / (1) / ....
459 0 : *pDigitLvl = GetDigitLevel( rNd, n );
460 0 : return nLvl;
461 : }
462 : }
463 0 : return nLvl;
464 : }
465 :
466 0 : sal_Int32 SwAutoFormat::GetBigIndent( sal_Int32& rAktSpacePos ) const
467 : {
468 0 : SwTxtFrmInfo aFInfo( GetFrm( *m_pCurTxtNd ) );
469 0 : const SwTxtFrm* pNxtFrm = 0;
470 :
471 0 : if( !m_bMoreLines )
472 : {
473 0 : const SwTxtNode* pNxtNd = GetNextNode();
474 0 : if( !CanJoin( pNxtNd ) || !IsOneLine( *pNxtNd ) )
475 0 : return 0;
476 :
477 0 : pNxtFrm = GetFrm( *pNxtNd );
478 : }
479 :
480 0 : return aFInfo.GetBigIndent( rAktSpacePos, pNxtFrm );
481 : }
482 :
483 0 : sal_Bool SwAutoFormat::IsNoAlphaLine( const SwTxtNode& rNd ) const
484 : {
485 0 : const OUString& rStr = rNd.GetTxt();
486 0 : if( rStr.isEmpty() )
487 0 : return sal_False;
488 : // or better: determine via number of AlphaNum and !AlphaNum characters
489 0 : sal_Int32 nANChar = 0, nBlnk = 0;
490 :
491 0 : CharClass& rCC = GetCharClass( rNd.GetSwAttrSet().GetLanguage().GetLanguage() );
492 0 : for( sal_Int32 n = 0, nEnd = rStr.getLength(); n < nEnd; ++n )
493 0 : if( IsSpace( rStr[ n ] ) )
494 0 : ++nBlnk;
495 0 : else if( rCC.isLetterNumeric( rStr, n ))
496 0 : ++nANChar;
497 :
498 : // If there are 75% of non-alphanumeric characters, then sal_True
499 0 : sal_uLong nLen = rStr.getLength() - nBlnk;
500 0 : nLen = ( nLen * 3 ) / 4; // long overflow, if the strlen > sal_uInt16
501 0 : return sal_Int32(nLen) < (rStr.getLength() - nANChar - nBlnk);
502 : }
503 :
504 0 : bool SwAutoFormat::DoUnderline()
505 : {
506 0 : if( !m_aFlags.bSetBorder )
507 0 : return false;
508 :
509 0 : OUString const& rTxt(m_pCurTxtNd->GetTxt());
510 0 : int eState = 0;
511 0 : sal_Int32 nCnt = 0;
512 0 : while (nCnt < rTxt.getLength())
513 : {
514 0 : int eTmp = 0;
515 0 : switch (rTxt[nCnt])
516 : {
517 0 : case '-': eTmp = 1; break;
518 0 : case '_': eTmp = 2; break;
519 0 : case '=': eTmp = 3; break;
520 0 : case '*': eTmp = 4; break;
521 0 : case '~': eTmp = 5; break;
522 0 : case '#': eTmp = 6; break;
523 : default:
524 0 : return false;
525 : }
526 0 : if( 0 == eState )
527 0 : eState = eTmp;
528 0 : else if( eState != eTmp )
529 0 : return false;
530 0 : ++nCnt;
531 : }
532 :
533 0 : if( 2 < nCnt )
534 : {
535 : // then underline the previous paragraph if one exists
536 0 : DelEmptyLine( false );
537 0 : m_aDelPam.SetMark();
538 0 : m_aDelPam.GetMark()->nContent = 0;
539 :
540 0 : editeng::SvxBorderLine aLine;
541 0 : switch( eState )
542 : {
543 : case 1: // single, 0.05 pt
544 0 : aLine.SetBorderLineStyle(table::BorderLineStyle::SOLID);
545 0 : aLine.SetWidth( DEF_LINE_WIDTH_0 );
546 0 : break;
547 : case 2: // single, 1.0 pt
548 0 : aLine.SetBorderLineStyle(table::BorderLineStyle::SOLID);
549 0 : aLine.SetWidth( DEF_LINE_WIDTH_1 );
550 0 : break;
551 : case 3: // double, 1.0 pt
552 0 : aLine.SetBorderLineStyle(table::BorderLineStyle::DOUBLE);
553 0 : aLine.SetWidth( DEF_LINE_WIDTH_1 );
554 0 : break;
555 : case 4: // double (thick/thin), 4.0 pt
556 0 : aLine.SetBorderLineStyle(table::BorderLineStyle::THICKTHIN_SMALLGAP);
557 0 : aLine.SetWidth( DEF_LINE_WIDTH_3 );
558 0 : break;
559 : case 5: // double (thin/thick), 4.0 pt
560 0 : aLine.SetBorderLineStyle(table::BorderLineStyle::THINTHICK_SMALLGAP);
561 0 : aLine.SetWidth( DEF_LINE_WIDTH_3 );
562 0 : break;
563 : case 6: // double, 2.5 pt
564 0 : aLine.SetBorderLineStyle(table::BorderLineStyle::DOUBLE);
565 0 : aLine.SetWidth( DEF_LINE_WIDTH_2 );
566 0 : break;
567 : }
568 0 : SfxItemSet aSet(m_pDoc->GetAttrPool(),
569 : RES_PARATR_CONNECT_BORDER, RES_PARATR_CONNECT_BORDER,
570 : RES_BOX, RES_BOX,
571 0 : 0);
572 0 : aSet.Put( SwParaConnectBorderItem( sal_False ) );
573 0 : SvxBoxItem aBox( RES_BOX );
574 0 : aBox.SetLine( &aLine, BOX_LINE_BOTTOM );
575 0 : aBox.SetDistance( 42 ); // ~0,75 mm
576 0 : aSet.Put(aBox);
577 0 : m_pDoc->InsertItemSet( m_aDelPam, aSet, 0 );
578 :
579 0 : m_aDelPam.DeleteMark();
580 : }
581 0 : return 2 < nCnt;
582 : }
583 :
584 0 : bool SwAutoFormat::DoTable()
585 : {
586 0 : if( !m_aFlags.bCreateTable || !m_aFlags.bAFmtByInput ||
587 0 : m_pCurTxtNd->FindTableNode() )
588 0 : return false;
589 :
590 0 : const OUString& rTmp = m_pCurTxtNd->GetTxt();
591 0 : sal_Int32 nSttPlus = GetLeadingBlanks( rTmp );
592 0 : sal_Int32 nEndPlus = GetTrailingBlanks( rTmp );
593 : sal_Unicode cChar;
594 :
595 0 : if( 2 > nEndPlus - nSttPlus ||
596 0 : ( '+' != ( cChar = rTmp[nSttPlus]) && '|' != cChar ) ||
597 0 : ( '+' != ( cChar = rTmp[nEndPlus - 1]) && '|' != cChar ))
598 0 : return false;
599 :
600 0 : SwTxtFrmInfo aInfo( m_pCurTxtFrm );
601 :
602 0 : sal_Int32 n = nSttPlus;
603 0 : std::vector<sal_uInt16> aPosArr;
604 :
605 0 : while (n < rTmp.getLength())
606 : {
607 0 : switch (rTmp[n])
608 : {
609 : case '-':
610 : case '_':
611 : case '=':
612 : case ' ':
613 : case '\t':
614 0 : break;
615 :
616 : case '+':
617 : case '|':
618 0 : aPosArr.push_back( static_cast<sal_uInt16>(aInfo.GetCharPos(n)) );
619 0 : break;
620 :
621 : default:
622 0 : return false;
623 : }
624 0 : if( ++n == nEndPlus )
625 0 : break;
626 : }
627 :
628 0 : if( 1 < aPosArr.size() )
629 : {
630 : // get the text node's alignment
631 0 : sal_uInt16 nColCnt = aPosArr.size() - 1;
632 0 : SwTwips nSttPos = aPosArr[ 0 ];
633 : sal_Int16 eHori;
634 0 : switch( m_pCurTxtNd->GetSwAttrSet().GetAdjust().GetAdjust() )
635 : {
636 0 : case SVX_ADJUST_CENTER: eHori = text::HoriOrientation::CENTER; break;
637 0 : case SVX_ADJUST_RIGHT: eHori = text::HoriOrientation::RIGHT; break;
638 :
639 : default:
640 0 : if( nSttPos )
641 : {
642 0 : eHori = text::HoriOrientation::NONE;
643 : // then - as last - we need to add the current frame width into the array
644 0 : aPosArr.push_back( static_cast<sal_uInt16>(m_pCurTxtFrm->Frm().Width()) );
645 : }
646 : else
647 0 : eHori = text::HoriOrientation::LEFT;
648 0 : break;
649 : }
650 :
651 : // then create a table that matches the character
652 0 : DelEmptyLine();
653 0 : SwNodeIndex aIdx( m_aDelPam.GetPoint()->nNode );
654 0 : m_aDelPam.Move( fnMoveForward );
655 : m_pDoc->InsertTable( SwInsertTableOptions( tabopts::ALL_TBL_INS_ATTR , 1 ),
656 0 : *m_aDelPam.GetPoint(), 1, nColCnt, eHori,
657 0 : 0, &aPosArr );
658 0 : m_aDelPam.GetPoint()->nNode = aIdx;
659 : }
660 0 : return 1 < aPosArr.size();
661 : }
662 :
663 0 : OUString SwAutoFormat::DelLeadingBlanks( const OUString& rStr ) const
664 : {
665 : sal_Int32 nL, n;
666 0 : for( nL = rStr.getLength(), n = 0; n < nL && IsSpace( rStr[n] ); ++n )
667 : ;
668 0 : if( n ) // no Spaces
669 0 : return rStr.copy(n);
670 0 : return rStr;
671 : }
672 :
673 0 : OUString& SwAutoFormat::DelTrailingBlanks( OUString& rStr ) const
674 : {
675 0 : sal_Int32 nL = rStr.getLength(), n = nL;
676 0 : if( !nL )
677 0 : return rStr;
678 :
679 0 : while( --n && IsSpace( rStr[ n ] ) )
680 : ;
681 0 : if( n+1 != nL ) // no Spaces
682 0 : rStr = rStr.copy( 0, n+1 );
683 0 : return rStr;
684 : }
685 :
686 0 : sal_Int32 SwAutoFormat::GetLeadingBlanks( const OUString& rStr ) const
687 : {
688 : sal_Int32 nL;
689 : sal_Int32 n;
690 :
691 0 : for( nL = rStr.getLength(), n = 0; n < nL && IsSpace( rStr[ n ] ); ++n )
692 : ;
693 0 : return n;
694 : }
695 :
696 0 : sal_Int32 SwAutoFormat::GetTrailingBlanks( const OUString& rStr ) const
697 : {
698 0 : sal_Int32 nL = rStr.getLength(), n = nL;
699 0 : if( !nL )
700 0 : return 0;
701 :
702 0 : while( --n && IsSpace( rStr[ n ] ) )
703 : ;
704 0 : return ++n;
705 : }
706 :
707 0 : bool SwAutoFormat::IsFirstCharCapital( const SwTxtNode& rNd ) const
708 : {
709 0 : const OUString& rTxt = rNd.GetTxt();
710 0 : for( sal_Int32 n = 0, nEnd = rTxt.getLength(); n < nEnd; ++n )
711 0 : if (!IsSpace(rTxt[n]))
712 : {
713 0 : CharClass& rCC = GetCharClass( rNd.GetSwAttrSet().
714 0 : GetLanguage().GetLanguage() );
715 0 : sal_Int32 nCharType = rCC.getCharacterType( rTxt, n );
716 0 : return CharClass::isLetterType( nCharType ) &&
717 0 : 0 != ( i18n::KCharacterType::UPPER &
718 0 : nCharType );
719 : }
720 0 : return false;
721 : }
722 :
723 0 : sal_uInt16 SwAutoFormat::GetDigitLevel( const SwTxtNode& rNd, sal_Int32& rPos,
724 : OUString* pPrefix, OUString* pPostfix, OUString* pNumTypes ) const
725 : {
726 : // check for 1.) / 1. / 1.1.1 / (1). / (1) / ....
727 0 : const OUString& rTxt = rNd.GetTxt();
728 0 : sal_Int32 nPos = rPos;
729 0 : int eScan = NONE;
730 :
731 0 : sal_uInt16 nStart = 0;
732 0 : sal_uInt8 nDigitLvl = 0, nDigitCnt = 0;
733 : // count number of parenthesis to assure a sensible order is found
734 0 : sal_uInt16 nOpeningParentheses = 0;
735 0 : sal_uInt16 nClosingParentheses = 0;
736 :
737 0 : CharClass& rCC = GetCharClass( rNd.GetSwAttrSet().GetLanguage().GetLanguage() );
738 :
739 0 : while (nPos < rTxt.getLength() && nDigitLvl < MAXLEVEL - 1)
740 : {
741 0 : const sal_Unicode cCurrentChar = rTxt[nPos];
742 0 : if( ('0' <= cCurrentChar && '9' >= cCurrentChar) ||
743 0 : (0xff10 <= cCurrentChar && 0xff19 >= cCurrentChar) )
744 : {
745 0 : if( eScan & DELIM )
746 : {
747 0 : if( eScan & CHG ) // not if it starts with a number
748 : {
749 0 : ++nDigitLvl;
750 0 : if( pPostfix )
751 0 : *pPostfix += OUString((sal_Unicode)1);
752 : }
753 :
754 0 : if( pNumTypes )
755 0 : *pNumTypes += OUString((sal_Unicode)('0' + SVX_NUM_ARABIC));
756 :
757 0 : eScan = eScan | CHG;
758 : }
759 0 : else if( pNumTypes && !(eScan & DIGIT) )
760 0 : *pNumTypes += OUString((sal_Unicode)('0' + SVX_NUM_ARABIC));
761 :
762 0 : eScan &= ~DELIM; // remvoe Delim
763 0 : if( 0 != (eScan & ~CHG) && DIGIT != (eScan & ~CHG))
764 0 : return USHRT_MAX;
765 :
766 0 : eScan |= DIGIT; // add Digit
767 0 : if( 3 == ++nDigitCnt ) // more than 2 numbers are not an enum anymore
768 0 : return USHRT_MAX;
769 :
770 0 : nStart *= 10;
771 0 : nStart += cCurrentChar <= '9' ? cCurrentChar - '0' : cCurrentChar - 0xff10;
772 : }
773 0 : else if( rCC.isAlpha( rTxt, nPos ) )
774 : {
775 : bool bIsUpper =
776 0 : 0 != ( i18n::KCharacterType::UPPER &
777 0 : rCC.getCharacterType( rTxt, nPos ));
778 0 : sal_Unicode cLow = rCC.lowercase(rTxt, nPos, 1)[0], cNumTyp;
779 : int eTmpScan;
780 :
781 : // Roman numbers are "mdclxvi". Since we want to start numbering with c or d more often,
782 : // convert first to characters and later to roman numbers if needed.
783 : #ifdef WITH_ALPHANUM_AS_NUMFMT
784 : // detection of 'c' and 'd' a ROMAN numbering should not be done here
785 : if( 256 > cLow &&( (eScan & (LOWER_ROMAN|UPPER_ROMAN))
786 : ? strchr( "mdclxvi", cLow )
787 : : strchr( "mlxvi", cLow ) ))
788 : #else
789 0 : if( 256 > cLow && ( strchr( "mdclxvi", cLow ) ))
790 : #endif
791 : {
792 0 : if( bIsUpper )
793 0 : cNumTyp = '0' + SVX_NUM_ROMAN_UPPER, eTmpScan = UPPER_ROMAN;
794 : else
795 0 : cNumTyp = '0' + SVX_NUM_ROMAN_LOWER, eTmpScan = LOWER_ROMAN;
796 : }
797 0 : else if( bIsUpper )
798 0 : cNumTyp = '0' + SVX_NUM_CHARS_UPPER_LETTER, eTmpScan = UPPER_ALPHA;
799 : else
800 0 : cNumTyp = '0' + SVX_NUM_CHARS_LOWER_LETTER, eTmpScan = LOWER_ALPHA;
801 :
802 : // Switch to roman numbers (only for c/d!)
803 0 : if( 1 == nDigitCnt && ( eScan & (UPPER_ALPHA|LOWER_ALPHA) ) &&
804 0 : ( 3 == nStart || 4 == nStart) && 256 > cLow &&
805 0 : strchr( "mdclxvi", cLow ) &&
806 0 : (( eScan & UPPER_ALPHA ) ? (eTmpScan & (UPPER_ALPHA|UPPER_ROMAN))
807 0 : : (eTmpScan & (LOWER_ALPHA|LOWER_ROMAN))) )
808 : {
809 0 : sal_Unicode c = '0';
810 0 : nStart = 3 == nStart ? 100 : 500;
811 0 : if( UPPER_ALPHA == eTmpScan )
812 0 : eTmpScan = UPPER_ROMAN, c += SVX_NUM_ROMAN_UPPER;
813 : else
814 0 : eTmpScan = LOWER_ROMAN, c += SVX_NUM_ROMAN_LOWER;
815 :
816 0 : ( eScan &= ~(UPPER_ALPHA|LOWER_ALPHA)) |= eTmpScan;
817 0 : if( pNumTypes )
818 0 : (*pNumTypes) = pNumTypes->replaceAt( pNumTypes->getLength() - 1, 1, OUString(c) );
819 : }
820 :
821 0 : if( eScan & DELIM )
822 : {
823 0 : if( eScan & CHG ) // not if it starts with a number
824 : {
825 0 : ++nDigitLvl;
826 0 : if( pPostfix )
827 0 : *pPostfix += OUString((sal_Unicode)1);
828 : }
829 :
830 0 : if( pNumTypes )
831 0 : *pNumTypes += OUString(cNumTyp);
832 0 : eScan = eScan | CHG;
833 : }
834 0 : else if( pNumTypes && !(eScan & eTmpScan) )
835 0 : *pNumTypes += OUString(cNumTyp);
836 :
837 0 : eScan &= ~DELIM; // remove Delim
838 :
839 : // if another type is set, stop here
840 0 : if( 0 != ( eScan & ~CHG ) && eTmpScan != ( eScan & ~CHG ))
841 0 : return USHRT_MAX;
842 :
843 0 : if( eTmpScan & (UPPER_ALPHA | LOWER_ALPHA) )
844 : {
845 : // allow characters only if they appear once
846 0 : return USHRT_MAX;
847 : }
848 : else
849 : {
850 : // roman numbers, check if valid characters
851 : sal_uInt16 nVal;
852 0 : bool bError = false;
853 0 : switch( cLow )
854 : {
855 0 : case 'm': nVal = 1000; goto CHECK_ROMAN_1;
856 0 : case 'd': nVal = 500; goto CHECK_ROMAN_5;
857 0 : case 'c': nVal = 100; goto CHECK_ROMAN_1;
858 0 : case 'l': nVal = 50; goto CHECK_ROMAN_5;
859 0 : case 'x': nVal = 10; goto CHECK_ROMAN_1;
860 0 : case 'v': nVal = 5; goto CHECK_ROMAN_5;
861 :
862 : CHECK_ROMAN_1:
863 : {
864 0 : int nMod5 = nStart % (nVal * 5);
865 0 : int nLast = nStart % nVal;
866 0 : int n10 = nVal / 10;
867 :
868 0 : if( nMod5 == ((3 * nVal) + n10 ) ||
869 0 : nMod5 == ((4 * nVal) + n10 ) ||
870 : nLast == n10 )
871 0 : nStart = static_cast<sal_uInt16>(nStart + (n10 * 8));
872 0 : else if( nMod5 == 0 ||
873 0 : nMod5 == (1 * nVal) ||
874 0 : nMod5 == (2 * nVal) )
875 0 : nStart = nStart + nVal;
876 : else
877 0 : bError = true;
878 : }
879 0 : break;
880 :
881 : CHECK_ROMAN_5:
882 : {
883 0 : if( ( nStart / nVal ) & 1 )
884 0 : bError = true;
885 : else
886 : {
887 0 : int nMod = nStart % nVal;
888 0 : int n10 = nVal / 5;
889 0 : if( n10 == nMod )
890 0 : nStart = static_cast<sal_uInt16>(nStart + (3 * n10));
891 0 : else if( 0 == nMod )
892 0 : nStart = nStart + nVal;
893 : else
894 0 : bError = true;
895 : }
896 : }
897 0 : break;
898 :
899 : case 'i':
900 0 : if( nStart % 5 >= 3 )
901 0 : bError = true;
902 : else
903 0 : nStart += 1;
904 0 : break;
905 :
906 : default:
907 0 : bError = true;
908 : }
909 :
910 0 : if( bError )
911 0 : return USHRT_MAX;
912 : }
913 0 : eScan |= eTmpScan; // add Digit
914 0 : ++nDigitCnt;
915 : }
916 0 : else if( (256 > cCurrentChar &&
917 0 : strchr( ".)(", cCurrentChar )) ||
918 0 : 0x3002 == cCurrentChar /* Chinese trad. dot */||
919 0 : 0xff0e == cCurrentChar /* Japanese dot */||
920 0 : 0xFF08 == cCurrentChar /* opening bracket Chin./Jap.*/||
921 : 0xFF09 == cCurrentChar )/* closing bracket Chin./Jap. */
922 : {
923 0 : if(cCurrentChar == '(' || cCurrentChar == 0xFF09)
924 0 : nOpeningParentheses++;
925 0 : else if(cCurrentChar == ')'|| cCurrentChar == 0xFF08)
926 0 : nClosingParentheses++;
927 : // only if no numbers were read until here
928 0 : if( pPrefix && !( eScan & ( NO_DELIM | CHG )) )
929 0 : *pPrefix += OUString(rTxt[nPos]);
930 0 : else if( pPostfix )
931 0 : *pPostfix += OUString(rTxt[nPos]);
932 :
933 0 : if( NO_DELIM & eScan )
934 : {
935 0 : eScan |= CHG;
936 0 : if( pPrefix )
937 : *pPrefix += OUString((sal_Unicode)1)
938 0 : + OUString::number( nStart );
939 : }
940 0 : eScan &= ~NO_DELIM; // remove Delim
941 0 : eScan |= DELIM; // add Digit
942 0 : nDigitCnt = 0;
943 0 : nStart = 0;
944 : }
945 : else
946 : break;
947 0 : ++nPos;
948 : }
949 0 : if( !( CHG & eScan ) || rPos == nPos ||
950 0 : nPos == rTxt.getLength() || !IsSpace(rTxt[nPos]) ||
951 : (nOpeningParentheses > nClosingParentheses))
952 0 : return USHRT_MAX;
953 :
954 0 : if( (NO_DELIM & eScan) && pPrefix ) // do not forget the last one
955 0 : *pPrefix += OUString((sal_Unicode)1) + OUString::number( nStart );
956 :
957 0 : rPos = nPos;
958 0 : return nDigitLvl; // 0 .. 9 (MAXLEVEL - 1)
959 : }
960 :
961 0 : void SwAutoFormat::SetColl( sal_uInt16 nId, bool bHdLineOrText )
962 : {
963 0 : m_aDelPam.DeleteMark();
964 0 : m_aDelPam.GetPoint()->nNode = m_aNdIdx;
965 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTxtNd, 0 );
966 :
967 : // keep hard tabs, alignment, language, hyphenation, DropCaps and nearly all frame attributes
968 0 : SfxItemSet aSet( m_pDoc->GetAttrPool(),
969 : RES_PARATR_ADJUST, RES_PARATR_ADJUST,
970 : RES_PARATR_TABSTOP, RES_PARATR_DROP,
971 : RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
972 : RES_BACKGROUND, RES_SHADOW,
973 0 : 0 );
974 :
975 0 : if( m_pCurTxtNd->HasSwAttrSet() )
976 : {
977 0 : aSet.Put( *m_pCurTxtNd->GetpSwAttrSet() );
978 : // take HeaderLine/TextBody only if centered or right aligned, otherwise only justification
979 : SvxAdjustItem* pAdj;
980 0 : if( SFX_ITEM_SET == aSet.GetItemState( RES_PARATR_ADJUST,
981 0 : false, (const SfxPoolItem**)&pAdj ))
982 : {
983 0 : SvxAdjust eAdj = pAdj->GetAdjust();
984 0 : if( bHdLineOrText ? (SVX_ADJUST_RIGHT != eAdj &&
985 : SVX_ADJUST_CENTER != eAdj)
986 : : SVX_ADJUST_BLOCK != eAdj )
987 0 : aSet.ClearItem( RES_PARATR_ADJUST );
988 : }
989 : }
990 :
991 0 : m_pDoc->SetTxtFmtCollByAutoFmt( *m_aDelPam.GetPoint(), nId, &aSet );
992 0 : }
993 :
994 0 : bool SwAutoFormat::HasSelBlanks( SwPaM& rPam ) const
995 : {
996 : // Is there a Blank at the beginning or end?
997 : // Do not delete it, it will be inserted again.
998 0 : SwPosition * pPos = rPam.End();
999 0 : sal_Int32 nBlnkPos = pPos->nContent.GetIndex();
1000 0 : SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
1001 0 : if (nBlnkPos && nBlnkPos-- < pTxtNd->GetTxt().getLength() &&
1002 0 : (' ' == pTxtNd->GetTxt()[nBlnkPos]))
1003 0 : pPos->nContent--;
1004 : else
1005 : {
1006 0 : pPos = rPam.GetPoint() == pPos ? rPam.GetMark() : rPam.GetPoint();
1007 0 : nBlnkPos = pPos->nContent.GetIndex();
1008 0 : pTxtNd = pPos->nNode.GetNode().GetTxtNode();
1009 0 : if (nBlnkPos < pTxtNd->GetTxt().getLength() &&
1010 0 : (' ' == pTxtNd->GetTxt()[nBlnkPos]))
1011 0 : pPos->nContent++;
1012 : else
1013 0 : return false;
1014 : }
1015 0 : return true;
1016 : }
1017 :
1018 0 : bool SwAutoFormat::HasBreakAttr( const SwTxtNode& rTxtNd ) const
1019 : {
1020 0 : const SfxItemSet* pSet = rTxtNd.GetpSwAttrSet();
1021 0 : if( !pSet )
1022 0 : return false;
1023 :
1024 : const SfxPoolItem* pItem;
1025 0 : if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, false, &pItem )
1026 0 : && SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak() )
1027 0 : return true;
1028 :
1029 0 : if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, false, &pItem )
1030 0 : && ((SwFmtPageDesc*)pItem)->GetPageDesc()
1031 0 : && nsUseOnPage::PD_NONE != ((SwFmtPageDesc*)pItem)->GetPageDesc()->GetUseOn() )
1032 0 : return true;
1033 0 : return false;
1034 : }
1035 :
1036 : /// Is there a dot at the end?
1037 0 : bool SwAutoFormat::IsSentenceAtEnd( const SwTxtNode& rTxtNd ) const
1038 : {
1039 0 : const OUString& rStr = rTxtNd.GetTxt();
1040 0 : sal_Int32 n = rStr.getLength();
1041 0 : if( !n )
1042 0 : return true;
1043 :
1044 0 : while( --n && IsSpace( rStr[ n ] ) )
1045 : ;
1046 0 : return '.' == rStr[ n ];
1047 : }
1048 :
1049 : /// Delete beginning and/or end in a node
1050 0 : void SwAutoFormat::DeleteCurrentParagraph( bool bStart, bool bEnd )
1051 : {
1052 0 : if( m_aFlags.bAFmtByInput
1053 : ? m_aFlags.bAFmtByInpDelSpacesAtSttEnd
1054 : : m_aFlags.bAFmtDelSpacesAtSttEnd )
1055 : {
1056 : // delete blanks at the end of the current and at the beginning of the next one
1057 0 : m_aDelPam.DeleteMark();
1058 0 : m_aDelPam.GetPoint()->nNode = m_aNdIdx;
1059 0 : sal_Int32 nPos(0);
1060 0 : if( bStart && 0 != ( nPos = GetLeadingBlanks( m_pCurTxtNd->GetTxt() )))
1061 : {
1062 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTxtNd, 0 );
1063 0 : m_aDelPam.SetMark();
1064 0 : m_aDelPam.GetPoint()->nContent = nPos;
1065 0 : DeleteSel( m_aDelPam );
1066 0 : m_aDelPam.DeleteMark();
1067 : }
1068 0 : if (bEnd && m_pCurTxtNd->GetTxt().getLength() !=
1069 0 : ( nPos = GetTrailingBlanks( m_pCurTxtNd->GetTxt() )) )
1070 : {
1071 0 : m_aDelPam.GetPoint()->nContent.Assign(
1072 0 : m_pCurTxtNd, m_pCurTxtNd->GetTxt().getLength());
1073 0 : m_aDelPam.SetMark();
1074 0 : m_aDelPam.GetPoint()->nContent = nPos;
1075 0 : DeleteSel( m_aDelPam );
1076 0 : m_aDelPam.DeleteMark();
1077 : }
1078 : }
1079 0 : }
1080 :
1081 0 : void SwAutoFormat::DeleteSel( SwPaM& rDelPam )
1082 : {
1083 0 : if( m_aFlags.bWithRedlining )
1084 : {
1085 : // Add to Shell-Cursor-Ring so that DelPam will be moved as well!
1086 0 : SwPaM* pShCrsr = m_pEditShell->_GetCrsr();
1087 0 : SwPaM aTmp( *m_pCurTxtNd, 0, pShCrsr );
1088 :
1089 0 : Ring *pPrev = rDelPam.GetPrev();
1090 0 : rDelPam.MoveRingTo( pShCrsr );
1091 :
1092 0 : m_pEditShell->DeleteSel( rDelPam );
1093 :
1094 : // and remove Pam again:
1095 0 : Ring *p, *pNext = (Ring*)&rDelPam;
1096 0 : do {
1097 0 : p = pNext;
1098 0 : pNext = p->GetNext();
1099 0 : p->MoveTo( &rDelPam );
1100 : } while( p != pPrev );
1101 :
1102 0 : m_aNdIdx = aTmp.GetPoint()->nNode;
1103 0 : m_pCurTxtNd = m_aNdIdx.GetNode().GetTxtNode();
1104 : }
1105 : else
1106 0 : m_pEditShell->DeleteSel( rDelPam );
1107 0 : }
1108 :
1109 0 : bool SwAutoFormat::DeleteCurNxtPara( const OUString& rNxtPara )
1110 : {
1111 : // delete blanks at the end of the current and at the beginning of the next one
1112 0 : m_aDelPam.DeleteMark();
1113 0 : m_aDelPam.GetPoint()->nNode = m_aNdIdx;
1114 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTxtNd,
1115 0 : GetTrailingBlanks( m_pCurTxtNd->GetTxt() ) );
1116 0 : m_aDelPam.SetMark();
1117 :
1118 0 : m_aDelPam.GetPoint()->nNode++;
1119 0 : SwTxtNode* pTNd = m_aDelPam.GetNode()->GetTxtNode();
1120 0 : if( !pTNd )
1121 : {
1122 : // then delete only up to end of the paragraph
1123 0 : m_aDelPam.GetPoint()->nNode--;
1124 0 : m_aDelPam.GetPoint()->nContent = m_pCurTxtNd->GetTxt().getLength();
1125 : }
1126 : else
1127 0 : m_aDelPam.GetPoint()->nContent.Assign( pTNd,
1128 0 : GetLeadingBlanks( rNxtPara ));
1129 :
1130 : // Is there a Blank at the beginning or end?
1131 : // Do not delete it, it will be inserted again.
1132 0 : bool bHasBlnks = HasSelBlanks( m_aDelPam );
1133 :
1134 0 : if( *m_aDelPam.GetPoint() != *m_aDelPam.GetMark() )
1135 0 : DeleteSel( m_aDelPam );
1136 0 : m_aDelPam.DeleteMark();
1137 :
1138 0 : return !bHasBlnks;
1139 : }
1140 :
1141 0 : void SwAutoFormat::DelEmptyLine( bool bTstNextPara )
1142 : {
1143 0 : SetRedlineTxt( STR_AUTOFMTREDL_DEL_EMPTY_PARA );
1144 : // delete blanks in empty paragraph
1145 0 : m_aDelPam.DeleteMark();
1146 0 : m_aDelPam.GetPoint()->nNode = m_aNdIdx;
1147 0 : m_aDelPam.GetPoint()->nContent.Assign(
1148 0 : m_pCurTxtNd, m_pCurTxtNd->GetTxt().getLength() );
1149 0 : m_aDelPam.SetMark();
1150 :
1151 0 : m_aDelPam.GetMark()->nNode--;
1152 0 : SwTxtNode* pTNd = m_aDelPam.GetNode( false )->GetTxtNode();
1153 0 : if( pTNd )
1154 : // first use the previous text node
1155 0 : m_aDelPam.GetMark()->nContent.Assign(pTNd, pTNd->GetTxt().getLength());
1156 0 : else if( bTstNextPara )
1157 : {
1158 : // then try the next (at the beginning of a Doc, table cells, borders, ...)
1159 0 : m_aDelPam.GetMark()->nNode += 2;
1160 0 : pTNd = m_aDelPam.GetNode( false )->GetTxtNode();
1161 0 : if( pTNd )
1162 : {
1163 0 : m_aDelPam.GetMark()->nContent.Assign( pTNd, 0 );
1164 0 : m_aDelPam.GetPoint()->nContent = 0;
1165 : }
1166 : }
1167 : else
1168 : {
1169 0 : m_aDelPam.GetMark()->nNode = m_aNdIdx;
1170 0 : m_aDelPam.GetMark()->nContent = 0;
1171 0 : pTNd = m_pCurTxtNd;
1172 : }
1173 0 : if( pTNd )
1174 0 : DeleteSel( m_aDelPam );
1175 :
1176 0 : m_aDelPam.DeleteMark();
1177 0 : ClearRedlineTxt();
1178 0 : }
1179 :
1180 0 : void SwAutoFormat::DelMoreLinesBlanks( bool bWithLineBreaks )
1181 : {
1182 0 : if( m_aFlags.bAFmtByInput
1183 : ? m_aFlags.bAFmtByInpDelSpacesBetweenLines
1184 : : m_aFlags.bAFmtDelSpacesBetweenLines )
1185 : {
1186 : // delete all blanks on the left and right of the indentation
1187 0 : m_aDelPam.DeleteMark();
1188 0 : m_aDelPam.GetPoint()->nNode = m_aNdIdx;
1189 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTxtNd, 0 );
1190 :
1191 0 : SwTxtFrmInfo aFInfo( m_pCurTxtFrm );
1192 0 : aFInfo.GetSpaces( m_aDelPam, !m_aFlags.bAFmtByInput || bWithLineBreaks );
1193 :
1194 : SwPaM* pNxt;
1195 : do {
1196 0 : pNxt = (SwPaM*)m_aDelPam.GetNext();
1197 0 : if( pNxt->HasMark() && *pNxt->GetPoint() != *pNxt->GetMark() )
1198 : {
1199 0 : bool bHasBlnks = HasSelBlanks( *pNxt );
1200 0 : DeleteSel( *pNxt );
1201 0 : if( !bHasBlnks )
1202 : {
1203 0 : m_pDoc->InsertString( *pNxt, OUString(' ') );
1204 : }
1205 : }
1206 :
1207 0 : if( pNxt == &m_aDelPam )
1208 0 : break;
1209 0 : delete pNxt;
1210 : } while( true );
1211 :
1212 0 : m_aDelPam.DeleteMark();
1213 : }
1214 0 : }
1215 :
1216 : // delete the previous paragraph
1217 0 : void SwAutoFormat::DelPrevPara()
1218 : {
1219 0 : m_aDelPam.DeleteMark();
1220 0 : m_aDelPam.GetPoint()->nNode = m_aNdIdx;
1221 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTxtNd, 0 );
1222 0 : m_aDelPam.SetMark();
1223 :
1224 0 : m_aDelPam.GetPoint()->nNode--;
1225 0 : SwTxtNode* pTNd = m_aDelPam.GetNode()->GetTxtNode();
1226 0 : if( pTNd )
1227 : {
1228 : // use the previous text node first
1229 0 : m_aDelPam.GetPoint()->nContent.Assign(pTNd, pTNd->GetTxt().getLength());
1230 0 : DeleteSel( m_aDelPam );
1231 : }
1232 0 : m_aDelPam.DeleteMark();
1233 0 : }
1234 :
1235 0 : void SwAutoFormat::BuildIndent()
1236 : {
1237 0 : SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_INDENT );
1238 :
1239 : // read all succeeding paragraphs that belong to this indentation
1240 0 : bool bBreak = true;
1241 0 : if( m_bMoreLines )
1242 0 : DelMoreLinesBlanks( true );
1243 : else
1244 0 : bBreak = !IsFastFullLine( *m_pCurTxtNd ) ||
1245 0 : IsBlanksInString( *m_pCurTxtNd ) ||
1246 0 : IsSentenceAtEnd( *m_pCurTxtNd );
1247 0 : SetColl( RES_POOLCOLL_TEXT_IDENT );
1248 0 : if( !bBreak )
1249 : {
1250 0 : SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES );
1251 0 : const SwTxtNode* pNxtNd = GetNextNode();
1252 0 : if( pNxtNd && !m_bEnd )
1253 : {
1254 0 : do {
1255 0 : bBreak = !IsFastFullLine( *pNxtNd ) ||
1256 0 : IsBlanksInString( *pNxtNd ) ||
1257 0 : IsSentenceAtEnd( *pNxtNd );
1258 0 : if( DeleteCurNxtPara( pNxtNd->GetTxt() ))
1259 : {
1260 0 : m_pDoc->InsertString( m_aDelPam, OUString(' ') );
1261 : }
1262 0 : if( bBreak )
1263 0 : break;
1264 0 : pNxtNd = GetNextNode();
1265 0 : } while( CanJoin( pNxtNd ) &&
1266 0 : !CalcLevel( *pNxtNd ) );
1267 : }
1268 : }
1269 0 : DeleteCurrentParagraph( true, true );
1270 0 : AutoCorrect();
1271 0 : }
1272 :
1273 0 : void SwAutoFormat::BuildTextIndent()
1274 : {
1275 0 : SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_TEXT_INDENT);
1276 : // read all succeeding paragraphs that belong to this indentation
1277 0 : bool bBreak = true;
1278 0 : if( m_bMoreLines )
1279 0 : DelMoreLinesBlanks( true );
1280 : else
1281 0 : bBreak = !IsFastFullLine( *m_pCurTxtNd ) ||
1282 0 : IsBlanksInString( *m_pCurTxtNd ) ||
1283 0 : IsSentenceAtEnd( *m_pCurTxtNd );
1284 :
1285 0 : if( m_aFlags.bAFmtByInput )
1286 0 : m_pCurTxtNd->SetAutoFmtLvl( (sal_uInt8)CalcLevel( *m_pCurTxtNd ) );
1287 :
1288 0 : SetColl( RES_POOLCOLL_TEXT_MOVE );
1289 0 : if( !bBreak )
1290 : {
1291 0 : SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES );
1292 0 : const SwTxtNode* pNxtNd = GetNextNode();
1293 0 : while( CanJoin( pNxtNd ) &&
1294 0 : CalcLevel( *pNxtNd ) )
1295 : {
1296 0 : bBreak = !IsFastFullLine( *pNxtNd ) || IsBlanksInString( *pNxtNd ) ||
1297 0 : IsSentenceAtEnd( *pNxtNd );
1298 0 : if( DeleteCurNxtPara( pNxtNd->GetTxt() ) )
1299 : {
1300 0 : m_pDoc->InsertString( m_aDelPam, OUString(' ') );
1301 : }
1302 0 : if( bBreak )
1303 0 : break;
1304 0 : pNxtNd = GetNextNode();
1305 : }
1306 : }
1307 0 : DeleteCurrentParagraph( true, true );
1308 0 : AutoCorrect();
1309 0 : }
1310 :
1311 0 : void SwAutoFormat::BuildText()
1312 : {
1313 0 : SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_TEXT );
1314 : // read all succeeding paragraphs that belong to this text without indentation
1315 0 : bool bBreak = true;
1316 0 : if( m_bMoreLines )
1317 0 : DelMoreLinesBlanks();
1318 : else
1319 0 : bBreak = !IsFastFullLine( *m_pCurTxtNd ) ||
1320 0 : IsBlanksInString( *m_pCurTxtNd ) ||
1321 0 : IsSentenceAtEnd( *m_pCurTxtNd );
1322 0 : SetColl( RES_POOLCOLL_TEXT, true );
1323 0 : if( !bBreak )
1324 : {
1325 0 : SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES );
1326 0 : const SwTxtNode* pNxtNd = GetNextNode();
1327 0 : while( CanJoin( pNxtNd ) &&
1328 0 : !CalcLevel( *pNxtNd ) )
1329 : {
1330 0 : bBreak = !IsFastFullLine( *pNxtNd ) || IsBlanksInString( *pNxtNd ) ||
1331 0 : IsSentenceAtEnd( *pNxtNd );
1332 0 : if( DeleteCurNxtPara( pNxtNd->GetTxt() ) )
1333 : {
1334 0 : m_pDoc->InsertString( m_aDelPam, OUString(' ') );
1335 : }
1336 0 : if( bBreak )
1337 0 : break;
1338 0 : const SwTxtNode* pCurrNode = pNxtNd;
1339 0 : pNxtNd = GetNextNode();
1340 0 : if(!pNxtNd || pCurrNode == pNxtNd)
1341 : break;
1342 : }
1343 : }
1344 0 : DeleteCurrentParagraph( true, true );
1345 0 : AutoCorrect();
1346 0 : }
1347 :
1348 0 : void SwAutoFormat::BuildEnum( sal_uInt16 nLvl, sal_uInt16 nDigitLevel )
1349 : {
1350 0 : SetRedlineTxt( STR_AUTOFMTREDL_SET_NUMBULET );
1351 :
1352 0 : bool bBreak = true;
1353 :
1354 : // first, determine current indentation and frame width
1355 0 : SwTwips nFrmWidth = m_pCurTxtFrm->Prt().Width();;
1356 : SwTwips nLeftTxtPos;
1357 : {
1358 0 : sal_Int32 nPos(0);
1359 0 : while (nPos < m_pCurTxtNd->GetTxt().getLength() &&
1360 0 : IsSpace(m_pCurTxtNd->GetTxt()[nPos]))
1361 : {
1362 0 : ++nPos;
1363 : }
1364 :
1365 0 : SwTxtFrmInfo aInfo( m_pCurTxtFrm );
1366 0 : nLeftTxtPos = aInfo.GetCharPos(nPos);
1367 0 : nLeftTxtPos -= m_pCurTxtNd->GetSwAttrSet().GetLRSpace().GetLeft();
1368 : }
1369 :
1370 0 : if( m_bMoreLines )
1371 0 : DelMoreLinesBlanks();
1372 : else
1373 0 : bBreak = !IsFastFullLine( *m_pCurTxtNd ) ||
1374 0 : IsBlanksInString( *m_pCurTxtNd ) ||
1375 0 : IsSentenceAtEnd( *m_pCurTxtNd );
1376 0 : sal_Bool bRTL = m_pEditShell->IsInRightToLeftText();
1377 0 : DeleteCurrentParagraph( true, true );
1378 :
1379 0 : bool bChgBullet = false, bChgEnum = false;
1380 0 : sal_Int32 nAutoCorrPos = 0;
1381 :
1382 : // if numbering is set, get the current one
1383 : SwNumRule aRule( m_pDoc->GetUniqueNumRuleName(),
1384 : // #i89178#
1385 0 : numfunc::GetDefaultPositionAndSpaceMode() );
1386 :
1387 0 : const SwNumRule* pCur = 0;
1388 0 : if( m_aFlags.bSetNumRule && 0 != (pCur = m_pCurTxtNd->GetNumRule()) )
1389 0 : aRule = *pCur;
1390 :
1391 : // replace bullet character with defined one
1392 0 : const OUString& rStr = m_pCurTxtNd->GetTxt();
1393 0 : sal_Int32 nTxtStt = 0;
1394 : const sal_Unicode* pFndBulletChr;
1395 0 : if( m_aFlags.bChgEnumNum &&
1396 0 : 2 < rStr.getLength() &&
1397 0 : 0 != ( pFndBulletChr = StrChr( pBulletChar, rStr[ nTxtStt ] ))
1398 0 : && IsSpace( rStr[ nTxtStt + 1 ] ) )
1399 : {
1400 0 : if( m_aFlags.bAFmtByInput )
1401 : {
1402 0 : if( m_aFlags.bSetNumRule )
1403 : {
1404 : SwCharFmt* pCFmt = m_pDoc->GetCharFmtFromPool(
1405 0 : RES_POOLCHR_BUL_LEVEL );
1406 0 : bChgBullet = true;
1407 : // Was the format already somewhere adjusted?
1408 0 : if( !aRule.GetNumFmt( nLvl ) )
1409 : {
1410 0 : int nBulletPos = pFndBulletChr - pBulletChar;
1411 : sal_Unicode cBullChar;
1412 0 : const Font* pBullFnt( 0 );
1413 0 : if( nBulletPos < cnPosEnDash )
1414 : {
1415 0 : cBullChar = m_aFlags.cBullet;
1416 0 : pBullFnt = &m_aFlags.aBulletFont;
1417 : }
1418 : else
1419 : {
1420 : cBullChar = nBulletPos < cnPosEmDash
1421 : ? cStarSymbolEnDash
1422 0 : : cStarSymbolEmDash;
1423 : // #i63395#
1424 : // Only apply user defined default bullet font
1425 0 : if ( numfunc::IsDefBulletFontUserDefined() )
1426 : {
1427 0 : pBullFnt = &numfunc::GetDefBulletFont();
1428 : }
1429 : }
1430 :
1431 0 : sal_uInt16 nAbsPos = lBullIndent;
1432 : sal_uInt16 nSpaceSteps = nLvl
1433 0 : ? sal_uInt16(nLeftTxtPos / nLvl)
1434 0 : : lBullIndent;
1435 0 : for( sal_uInt8 n = 0; n < MAXLEVEL; ++n, nAbsPos = nAbsPos + nSpaceSteps )
1436 : {
1437 0 : SwNumFmt aFmt( aRule.Get( n ) );
1438 0 : aFmt.SetBulletFont( pBullFnt );
1439 0 : aFmt.SetBulletChar( cBullChar );
1440 0 : aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1441 : // #i93908# clear suffix for bullet lists
1442 0 : aFmt.SetPrefix(OUString());
1443 0 : aFmt.SetSuffix(OUString());
1444 0 : aFmt.SetFirstLineOffset( lBullFirstLineOffset );
1445 0 : aFmt.SetAbsLSpace( nAbsPos );
1446 0 : if( !aFmt.GetCharFmt() )
1447 0 : aFmt.SetCharFmt( pCFmt );
1448 0 : if( bRTL )
1449 0 : aFmt.SetNumAdjust( SVX_ADJUST_RIGHT );
1450 :
1451 0 : aRule.Set( n, aFmt );
1452 :
1453 0 : if( n == nLvl &&
1454 0 : nFrmWidth < ( nSpaceSteps * MAXLEVEL ) )
1455 0 : nSpaceSteps = static_cast<sal_uInt16>(( nFrmWidth - nLeftTxtPos ) /
1456 0 : ( MAXLEVEL - nLvl ));
1457 0 : }
1458 : }
1459 : }
1460 : }
1461 : else
1462 : {
1463 0 : bChgBullet = true;
1464 0 : SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_BUL_LEVEL1 + ( std::min( nLvl, cnNumBullColls ) * 4 )) );
1465 : }
1466 : }
1467 : else
1468 : {
1469 : // Then it is a numbering
1470 :
1471 : //JP 21.11.97: The NumLevel is either the DigitLevel or, if the latter is not existent or 0,
1472 : // it is determined by the indentation level.
1473 :
1474 0 : OUString aPostfix, aPrefix, aNumTypes;
1475 0 : if( USHRT_MAX != ( nDigitLevel = GetDigitLevel( *m_pCurTxtNd, nTxtStt,
1476 0 : &aPrefix, &aPostfix, &aNumTypes )) )
1477 : {
1478 0 : bChgEnum = true;
1479 :
1480 : // Level 0 and Indentation, determine level by left indentation and default NumIndent
1481 0 : if( !nDigitLevel && nLeftTxtPos )
1482 0 : nLvl = std::min( sal_uInt16( nLeftTxtPos / lNumIndent ),
1483 0 : sal_uInt16( MAXLEVEL - 1 ) );
1484 : else
1485 0 : nLvl = nDigitLevel;
1486 : }
1487 :
1488 0 : if( bChgEnum && m_aFlags.bSetNumRule )
1489 : {
1490 0 : if( !pCur ) // adjust NumRule if it is new
1491 : {
1492 : SwCharFmt* pCFmt = m_pDoc->GetCharFmtFromPool(
1493 0 : RES_POOLCHR_NUM_LEVEL );
1494 0 : if( !nDigitLevel )
1495 : {
1496 0 : SwNumFmt aFmt( aRule.Get( nLvl ) );
1497 : aFmt.SetStart( static_cast<sal_uInt16>(aPrefix.getToken( 1,
1498 0 : (sal_Unicode)1 ).toInt32()));
1499 0 : aFmt.SetPrefix( aPrefix.getToken( 0, (sal_Unicode)1 ));
1500 0 : aFmt.SetSuffix( aPostfix.getToken( 0, (sal_Unicode)1 ));
1501 0 : aFmt.SetIncludeUpperLevels( 0 );
1502 :
1503 0 : if( !aFmt.GetCharFmt() )
1504 0 : aFmt.SetCharFmt( pCFmt );
1505 :
1506 0 : if( !aNumTypes.isEmpty() )
1507 0 : aFmt.SetNumberingType(aNumTypes[ 0 ] - '0');
1508 :
1509 0 : if( bRTL )
1510 0 : aFmt.SetNumAdjust( SVX_ADJUST_RIGHT );
1511 0 : aRule.Set( nLvl, aFmt );
1512 : }
1513 : else
1514 : {
1515 0 : sal_uInt16 nSpaceSteps = nLvl ? sal_uInt16(nLeftTxtPos / nLvl) : 0;
1516 : sal_uInt8 n;
1517 0 : for( n = 0; n <= nLvl; ++n )
1518 : {
1519 0 : SwNumFmt aFmt( aRule.Get( n ) );
1520 :
1521 0 : aFmt.SetStart( static_cast<sal_uInt16>(aPrefix.getToken( n+1,
1522 0 : (sal_Unicode)1 ).toInt32() ));
1523 0 : if( !n )
1524 0 : aFmt.SetPrefix( aPrefix.getToken( n, (sal_Unicode)1 ));
1525 0 : aFmt.SetSuffix( aPostfix.getToken( n, (sal_Unicode)1 ));
1526 0 : aFmt.SetIncludeUpperLevels( MAXLEVEL );
1527 0 : if( n < aNumTypes.getLength() )
1528 0 : aFmt.SetNumberingType((aNumTypes[ n ] - '0'));
1529 :
1530 : aFmt.SetAbsLSpace( sal_uInt16( nSpaceSteps * n )
1531 0 : + lNumIndent );
1532 :
1533 0 : if( !aFmt.GetCharFmt() )
1534 0 : aFmt.SetCharFmt( pCFmt );
1535 0 : if( bRTL )
1536 0 : aFmt.SetNumAdjust( SVX_ADJUST_RIGHT );
1537 :
1538 0 : aRule.Set( n, aFmt );
1539 0 : }
1540 :
1541 : // Does it fit completely into the frame?
1542 0 : bool bDefStep = nFrmWidth < (nSpaceSteps * MAXLEVEL);
1543 0 : for( ; n < MAXLEVEL; ++n )
1544 : {
1545 0 : SwNumFmt aFmt( aRule.Get( n ) );
1546 0 : aFmt.SetIncludeUpperLevels( MAXLEVEL );
1547 0 : if( bDefStep )
1548 : aFmt.SetAbsLSpace( sal_uInt16( (nLeftTxtPos +
1549 0 : SwNumRule::GetNumIndent(static_cast<sal_uInt8>(n-nLvl)))));
1550 : else
1551 : aFmt.SetAbsLSpace( sal_uInt16( nSpaceSteps * n )
1552 0 : + lNumIndent );
1553 0 : aRule.Set( n, aFmt );
1554 0 : }
1555 : }
1556 0 : }
1557 : }
1558 0 : else if( !m_aFlags.bAFmtByInput )
1559 0 : SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_NUM_LEVEL1 + ( std::min( nLvl, cnNumBullColls ) * 4 ) ));
1560 : else
1561 0 : bChgEnum = false;
1562 : }
1563 :
1564 0 : if ( bChgEnum || bChgBullet )
1565 : {
1566 0 : m_aDelPam.DeleteMark();
1567 0 : m_aDelPam.GetPoint()->nNode = m_aNdIdx;
1568 :
1569 0 : if( m_aFlags.bSetNumRule )
1570 : {
1571 0 : if( m_aFlags.bAFmtByInput )
1572 : {
1573 0 : m_aDelPam.SetMark();
1574 0 : m_aDelPam.GetMark()->nNode++;
1575 0 : m_aDelPam.GetNode(false)->GetTxtNode()->SetAttrListLevel( nLvl );
1576 : }
1577 :
1578 0 : m_pCurTxtNd->SetAttrListLevel(nLvl);
1579 0 : m_pCurTxtNd->SetNumLSpace( true );
1580 :
1581 : // start new list
1582 0 : m_pDoc->SetNumRule( m_aDelPam, aRule, true );
1583 0 : m_aDelPam.DeleteMark();
1584 :
1585 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTxtNd, 0 );
1586 : }
1587 : else
1588 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTxtNd,
1589 0 : bChgEnum ? nTxtStt : 0 );
1590 0 : m_aDelPam.SetMark();
1591 :
1592 0 : if ( bChgBullet )
1593 0 : nTxtStt += 2;
1594 :
1595 0 : while( nTxtStt < rStr.getLength() && IsSpace( rStr[ nTxtStt ] ))
1596 0 : nTxtStt++;
1597 :
1598 0 : m_aDelPam.GetPoint()->nContent = nTxtStt;
1599 0 : DeleteSel( m_aDelPam );
1600 :
1601 0 : if( !m_aFlags.bSetNumRule )
1602 : {
1603 0 : OUString sChgStr('\t');
1604 0 : if( bChgBullet )
1605 0 : sChgStr = OUString( m_aFlags.cBullet ) + sChgStr;
1606 0 : m_pDoc->InsertString( m_aDelPam, sChgStr );
1607 :
1608 0 : SfxItemSet aSet( m_pDoc->GetAttrPool(), aTxtNodeSetRange );
1609 0 : if( bChgBullet )
1610 : {
1611 0 : m_aDelPam.GetPoint()->nContent = 0;
1612 0 : m_aDelPam.SetMark();
1613 0 : m_aDelPam.GetMark()->nContent = 1;
1614 : SetAllScriptItem( aSet,
1615 : SvxFontItem( m_aFlags.aBulletFont.GetFamily(),
1616 0 : m_aFlags.aBulletFont.GetName(),
1617 0 : m_aFlags.aBulletFont.GetStyleName(),
1618 : m_aFlags.aBulletFont.GetPitch(),
1619 0 : m_aFlags.aBulletFont.GetCharSet(),
1620 0 : RES_CHRATR_FONT ) );
1621 0 : m_pDoc->SetFmtItemByAutoFmt( m_aDelPam, aSet );
1622 0 : m_aDelPam.DeleteMark();
1623 0 : nAutoCorrPos = 2;
1624 0 : aSet.ClearItem();
1625 : }
1626 0 : SvxTabStopItem aTStops( RES_PARATR_TABSTOP );
1627 0 : aTStops.Insert( SvxTabStop( 0 ) );
1628 0 : aSet.Put( aTStops );
1629 0 : m_pDoc->SetFmtItemByAutoFmt( m_aDelPam, aSet );
1630 : }
1631 : }
1632 :
1633 0 : if( bBreak )
1634 : {
1635 0 : AutoCorrect( nAutoCorrPos ); /* Offset due to Bullet + Tab */
1636 0 : return;
1637 : }
1638 :
1639 0 : const SwTxtNode* pNxtNd = GetNextNode();
1640 0 : while( CanJoin( pNxtNd ) &&
1641 0 : nLvl == CalcLevel( *pNxtNd ) )
1642 : {
1643 0 : SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES );
1644 0 : bBreak = !IsFastFullLine( *pNxtNd ) || IsBlanksInString( *pNxtNd ) ||
1645 0 : IsSentenceAtEnd( *pNxtNd );
1646 0 : if( DeleteCurNxtPara( pNxtNd->GetTxt() ) )
1647 : {
1648 0 : m_pDoc->InsertString( m_aDelPam, OUString(' ') );
1649 : }
1650 0 : if( bBreak )
1651 0 : break;
1652 0 : const SwTxtNode* pCurrNode = pNxtNd;
1653 0 : pNxtNd = GetNextNode();
1654 0 : if(!pNxtNd || pCurrNode == pNxtNd)
1655 : break;
1656 : }
1657 0 : DeleteCurrentParagraph( false, true );
1658 0 : AutoCorrect( nAutoCorrPos );
1659 : }
1660 :
1661 0 : void SwAutoFormat::BuildNegIndent( SwTwips nSpaces )
1662 : {
1663 0 : SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_NEG_INDENT );
1664 : // Test of contraposition (n words, divided by spaces/tabs, with same indentation in 2nd line)
1665 :
1666 : // read all succeeding paragraphs that belong to this enumeration
1667 0 : bool bBreak = true;
1668 0 : sal_Int32 nSpacePos = 0;
1669 0 : const sal_Int32 nTxtPos = GetBigIndent( nSpacePos );
1670 0 : if( m_bMoreLines )
1671 0 : DelMoreLinesBlanks( true );
1672 : else
1673 0 : bBreak = !IsFastFullLine( *m_pCurTxtNd ) ||
1674 0 : ( !nTxtPos && IsBlanksInString( *m_pCurTxtNd )) ||
1675 0 : IsSentenceAtEnd( *m_pCurTxtNd );
1676 :
1677 : SetColl( static_cast<sal_uInt16>( nTxtPos
1678 : ? RES_POOLCOLL_CONFRONTATION
1679 0 : : RES_POOLCOLL_TEXT_NEGIDENT ) );
1680 :
1681 0 : if( nTxtPos )
1682 : {
1683 0 : const OUString& rStr = m_pCurTxtNd->GetTxt();
1684 0 : bool bInsTab = true;
1685 :
1686 0 : if ('\t' == rStr[nSpacePos+1]) // leave tab alone
1687 : {
1688 0 : --nSpacePos;
1689 0 : bInsTab = false;
1690 : }
1691 :
1692 0 : sal_Int32 nSpaceStt = nSpacePos;
1693 0 : while (nSpaceStt && IsSpace(rStr[--nSpaceStt]))
1694 : ;
1695 0 : ++nSpaceStt;
1696 :
1697 0 : if (bInsTab && '\t' == rStr[nSpaceStt]) // leave tab alone
1698 : {
1699 0 : ++nSpaceStt;
1700 0 : bInsTab = false;
1701 : }
1702 :
1703 0 : m_aDelPam.DeleteMark();
1704 0 : m_aDelPam.GetPoint()->nNode = m_aNdIdx;
1705 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTxtNd, nSpacePos );
1706 :
1707 : // delete old Spaces, etc.
1708 0 : if( nSpaceStt < nSpacePos )
1709 : {
1710 0 : m_aDelPam.SetMark();
1711 0 : m_aDelPam.GetMark()->nContent = nSpaceStt;
1712 0 : DeleteSel( m_aDelPam );
1713 0 : if( bInsTab )
1714 : {
1715 0 : m_pDoc->InsertString( m_aDelPam, OUString('\t') );
1716 : }
1717 : }
1718 : }
1719 :
1720 0 : if( !bBreak )
1721 : {
1722 0 : SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES );
1723 0 : SwTxtFrmInfo aFInfo( m_pCurTxtFrm );
1724 0 : const SwTxtNode* pNxtNd = GetNextNode();
1725 0 : while( CanJoin( pNxtNd ) &&
1726 : 20 < std::abs( (long)(nSpaces - aFInfo.SetFrm(
1727 0 : GetFrm( *pNxtNd ) ).GetLineStart() ))
1728 : )
1729 : {
1730 0 : bBreak = !IsFastFullLine( *pNxtNd ) ||
1731 0 : IsBlanksInString( *pNxtNd ) ||
1732 0 : IsSentenceAtEnd( *pNxtNd );
1733 0 : if( DeleteCurNxtPara( pNxtNd->GetTxt() ) )
1734 : {
1735 0 : m_pDoc->InsertString( m_aDelPam, OUString(' ') );
1736 : }
1737 0 : if( bBreak )
1738 0 : break;
1739 0 : pNxtNd = GetNextNode();
1740 : }
1741 : }
1742 0 : DeleteCurrentParagraph( true, true );
1743 0 : AutoCorrect();
1744 0 : }
1745 :
1746 0 : void SwAutoFormat::BuildHeadLine( sal_uInt16 nLvl )
1747 : {
1748 0 : if( m_aFlags.bWithRedlining )
1749 : {
1750 0 : OUString sTxt(SwViewShell::GetShellRes()->GetAutoFmtNameLst()[
1751 0 : STR_AUTOFMTREDL_SET_TMPL_HEADLINE ] );
1752 0 : sTxt = sTxt.replaceAll( "$(ARG1)", OUString::number( nLvl + 1 ) );
1753 0 : m_pDoc->SetAutoFmtRedlineComment( &sTxt );
1754 : }
1755 :
1756 0 : SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + nLvl ), true );
1757 0 : if( m_aFlags.bAFmtByInput )
1758 : {
1759 0 : SwTxtFmtColl& rNxtColl = m_pCurTxtNd->GetTxtColl()->GetNextTxtFmtColl();
1760 :
1761 0 : DelPrevPara();
1762 :
1763 0 : DeleteCurrentParagraph( true, false );
1764 0 : (void)DeleteCurNxtPara( OUString() );
1765 :
1766 0 : m_aDelPam.DeleteMark();
1767 0 : m_aDelPam.GetPoint()->nNode = m_aNdIdx.GetIndex() + 1;
1768 0 : m_aDelPam.GetPoint()->nContent.Assign( m_aDelPam.GetCntntNode(), 0 );
1769 0 : m_pDoc->SetTxtFmtColl( m_aDelPam, &rNxtColl );
1770 : }
1771 : else
1772 : {
1773 0 : DeleteCurrentParagraph( true, true );
1774 0 : AutoCorrect();
1775 : }
1776 0 : }
1777 :
1778 : /// Start autocorrection for the current TextNode
1779 0 : void SwAutoFormat::AutoCorrect( sal_Int32 nPos )
1780 : {
1781 0 : SvxAutoCorrect* pATst = SvxAutoCorrCfg::Get().GetAutoCorrect();
1782 0 : long aSvxFlags = pATst->GetFlags( );
1783 0 : bool bReplaceQuote = ( aSvxFlags & ChgQuotes ) > 0;
1784 0 : bool bReplaceSglQuote = ( aSvxFlags & ChgSglQuotes ) > 0;
1785 :
1786 0 : if( m_aFlags.bAFmtByInput ||
1787 0 : (!m_aFlags.bAutoCorrect && !bReplaceQuote && !bReplaceSglQuote &&
1788 0 : !m_aFlags.bCptlSttSntnc && !m_aFlags.bCptlSttWrd &&
1789 0 : !m_aFlags.bChgOrdinalNumber &&
1790 0 : !m_aFlags.bChgToEnEmDash && !m_aFlags.bSetINetAttr &&
1791 0 : !m_aFlags.bChgWeightUnderl && !m_aFlags.bAddNonBrkSpace) )
1792 0 : return;
1793 :
1794 0 : const OUString* pTxt = &m_pCurTxtNd->GetTxt();
1795 0 : if (nPos >= pTxt->getLength())
1796 0 : return;
1797 :
1798 0 : bool bGetLanguage = m_aFlags.bChgOrdinalNumber ||
1799 0 : m_aFlags.bChgToEnEmDash || m_aFlags.bSetINetAttr ||
1800 0 : m_aFlags.bCptlSttWrd || m_aFlags.bCptlSttSntnc ||
1801 0 : m_aFlags.bAddNonBrkSpace;
1802 :
1803 0 : m_aDelPam.DeleteMark();
1804 0 : m_aDelPam.GetPoint()->nNode = m_aNdIdx;
1805 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTxtNd, 0 );
1806 :
1807 0 : SwAutoCorrDoc aACorrDoc( *m_pEditShell, m_aDelPam );
1808 :
1809 0 : SwTxtFrmInfo aFInfo( 0 );
1810 :
1811 0 : sal_Int32 nSttPos, nLastBlank = nPos;
1812 0 : sal_Bool bFirst = m_aFlags.bCptlSttSntnc, bFirstSent = bFirst;
1813 0 : sal_Unicode cChar = 0;
1814 :
1815 0 : CharClass& rAppCC = GetAppCharClass();
1816 :
1817 0 : do {
1818 0 : while (nPos < pTxt->getLength() && IsSpace(cChar = (*pTxt)[nPos]))
1819 0 : ++nPos;
1820 0 : if (nPos == pTxt->getLength())
1821 0 : break; // das wars
1822 :
1823 0 : if( ( ( bReplaceQuote && '\"' == cChar ) ||
1824 0 : ( bReplaceSglQuote && '\'' == cChar ) ) &&
1825 0 : (!nPos || ' ' == (*pTxt)[nPos-1]))
1826 : {
1827 :
1828 : // beachte: Sonderfall Symbolfonts !!!
1829 0 : if( !aFInfo.GetFrm() )
1830 0 : aFInfo.SetFrm( GetFrm( *m_pCurTxtNd ) );
1831 0 : if( !aFInfo.IsBullet( nPos ))
1832 : {
1833 0 : SetRedlineTxt( STR_AUTOFMTREDL_TYPO );
1834 0 : m_aDelPam.GetPoint()->nContent = nPos;
1835 0 : bool bSetHardBlank = false;
1836 :
1837 : OUString sReplace( pATst->GetQuote( aACorrDoc,
1838 0 : nPos, cChar, true ));
1839 :
1840 0 : m_aDelPam.SetMark();
1841 0 : m_aDelPam.GetPoint()->nContent = nPos+1;
1842 0 : if( 2 == sReplace.getLength() && ' ' == sReplace[ 1 ])
1843 : {
1844 0 : sReplace = sReplace.copy( 0, 1 );
1845 0 : bSetHardBlank = true;
1846 : }
1847 0 : m_pDoc->ReplaceRange( m_aDelPam, sReplace, false );
1848 :
1849 0 : if( m_aFlags.bWithRedlining )
1850 : {
1851 0 : m_aNdIdx = m_aDelPam.GetPoint()->nNode;
1852 0 : m_pCurTxtNd = m_aNdIdx.GetNode().GetTxtNode();
1853 0 : pTxt = &m_pCurTxtNd->GetTxt();
1854 0 : m_aDelPam.SetMark();
1855 0 : aFInfo.SetFrm( 0 );
1856 : }
1857 :
1858 0 : nPos += sReplace.getLength() - 1;
1859 0 : m_aDelPam.DeleteMark();
1860 0 : if( bSetHardBlank )
1861 : {
1862 0 : m_pDoc->InsertString( m_aDelPam, OUString(CHAR_HARDBLANK) );
1863 0 : ++nPos;
1864 0 : }
1865 : }
1866 : }
1867 :
1868 0 : bool bCallACorr = false;
1869 0 : int bBreak = 0;
1870 0 : if (nPos && IsSpace((*pTxt)[nPos-1]))
1871 0 : nLastBlank = nPos;
1872 0 : for (nSttPos = nPos; !bBreak && nPos < pTxt->getLength(); ++nPos)
1873 0 : switch (cChar = (*pTxt)[nPos])
1874 : {
1875 : case '\"':
1876 : case '\'':
1877 0 : if( ( cChar == '\"' && bReplaceQuote ) || ( cChar == '\'' && bReplaceSglQuote ) )
1878 : {
1879 : // consider Symbolfonts!
1880 0 : if( !aFInfo.GetFrm() )
1881 0 : aFInfo.SetFrm( GetFrm( *m_pCurTxtNd ) );
1882 0 : if( !aFInfo.IsBullet( nPos ))
1883 : {
1884 0 : SetRedlineTxt( STR_AUTOFMTREDL_TYPO );
1885 0 : bool bSetHardBlank = false;
1886 0 : m_aDelPam.GetPoint()->nContent = nPos;
1887 : OUString sReplace( pATst->GetQuote( aACorrDoc,
1888 0 : nPos, cChar, false ));
1889 :
1890 0 : if( 2 == sReplace.getLength() && ' ' == sReplace[ 0 ])
1891 : {
1892 0 : sReplace = sReplace.copy( 1 );
1893 0 : bSetHardBlank = true;
1894 : }
1895 :
1896 0 : m_aDelPam.SetMark();
1897 0 : m_aDelPam.GetPoint()->nContent = nPos+1;
1898 0 : m_pDoc->ReplaceRange( m_aDelPam, sReplace, false );
1899 :
1900 0 : if( m_aFlags.bWithRedlining )
1901 : {
1902 0 : m_aNdIdx = m_aDelPam.GetPoint()->nNode;
1903 0 : m_pCurTxtNd = m_aNdIdx.GetNode().GetTxtNode();
1904 0 : pTxt = &m_pCurTxtNd->GetTxt();
1905 0 : m_aDelPam.SetMark();
1906 0 : m_aDelPam.DeleteMark();
1907 0 : aFInfo.SetFrm( 0 );
1908 : }
1909 :
1910 0 : nPos += sReplace.getLength() - 1;
1911 0 : m_aDelPam.DeleteMark();
1912 :
1913 0 : if( bSetHardBlank )
1914 : {
1915 0 : m_aDelPam.GetPoint()->nContent = nPos;
1916 0 : m_pDoc->InsertString( m_aDelPam, OUString(CHAR_HARDBLANK) );
1917 0 : m_aDelPam.GetPoint()->nContent = ++nPos;
1918 0 : }
1919 : }
1920 : }
1921 0 : break;
1922 : case '*':
1923 : case '_':
1924 0 : if( m_aFlags.bChgWeightUnderl )
1925 : {
1926 : // consider Symbolfonts!
1927 0 : if( !aFInfo.GetFrm() )
1928 0 : aFInfo.SetFrm( GetFrm( *m_pCurTxtNd ) );
1929 0 : if( !aFInfo.IsBullet( nPos ))
1930 : {
1931 : SetRedlineTxt( '*' == cChar
1932 : ? STR_AUTOFMTREDL_BOLD
1933 0 : : STR_AUTOFMTREDL_UNDER );
1934 :
1935 0 : sal_Unicode cBlank = nSttPos ? (*pTxt)[nSttPos - 1] : 0;
1936 0 : m_aDelPam.GetPoint()->nContent = nPos;
1937 :
1938 0 : if( pATst->FnChgWeightUnderl( aACorrDoc, *pTxt,
1939 0 : nSttPos, nPos ))
1940 : {
1941 0 : if( m_aFlags.bWithRedlining )
1942 : {
1943 0 : m_aNdIdx = m_aDelPam.GetPoint()->nNode;
1944 0 : m_pCurTxtNd = m_aNdIdx.GetNode().GetTxtNode();
1945 0 : pTxt = &m_pCurTxtNd->GetTxt();
1946 0 : m_aDelPam.SetMark();
1947 0 : m_aDelPam.DeleteMark();
1948 0 : aFInfo.SetFrm( 0 );
1949 : }
1950 : //#125102# in case of the mode REDLINE_SHOW_DELETE the ** are still contained in pTxt
1951 0 : if(0 == (m_pDoc->GetRedlineMode() & nsRedlineMode_t::REDLINE_SHOW_DELETE))
1952 0 : nPos = m_aDelPam.GetPoint()->nContent.GetIndex() - 1;
1953 : // Was a character deleted before starting?
1954 0 : if (cBlank && cBlank != (*pTxt)[nSttPos - 1])
1955 0 : --nSttPos;
1956 : }
1957 : }
1958 : }
1959 0 : break;
1960 : case '/':
1961 0 : if ( m_aFlags.bAddNonBrkSpace )
1962 : {
1963 : LanguageType eLang = bGetLanguage
1964 0 : ? m_pCurTxtNd->GetLang( nSttPos )
1965 0 : : LANGUAGE_SYSTEM;
1966 :
1967 0 : SetRedlineTxt( STR_AUTOFMTREDL_NON_BREAK_SPACE );
1968 0 : if ( pATst->FnAddNonBrkSpace( aACorrDoc, *pTxt, nSttPos, nPos, eLang ) )
1969 0 : --nPos;
1970 : }
1971 0 : break;
1972 :
1973 : case '.':
1974 : case '!':
1975 : case '?':
1976 0 : if( m_aFlags.bCptlSttSntnc )
1977 0 : bFirstSent = sal_True;
1978 : /* fallthrough */
1979 : default:
1980 0 : if( !( rAppCC.isLetterNumeric( *pTxt, nPos )
1981 0 : || '/' == cChar )) // '/' should not be a word separator (e.g. '1/2' needs to be handled as one word for replacement)
1982 : {
1983 0 : --nPos; // revert ++nPos which was decremented in for loop
1984 0 : ++bBreak;
1985 : }
1986 0 : break;
1987 : }
1988 :
1989 0 : if( nPos == nSttPos )
1990 : {
1991 0 : if (++nPos == pTxt->getLength())
1992 0 : bCallACorr = true;
1993 : }
1994 : else
1995 0 : bCallACorr = true;
1996 :
1997 0 : if( bCallACorr )
1998 : {
1999 0 : bCallACorr = false;
2000 0 : m_aDelPam.GetPoint()->nContent = nPos;
2001 0 : SetRedlineTxt( STR_AUTOFMTREDL_USE_REPLACE );
2002 0 : if( m_aFlags.bAutoCorrect &&
2003 0 : aACorrDoc.ChgAutoCorrWord( nSttPos, nPos, *pATst, 0 ) )
2004 : {
2005 0 : nPos = m_aDelPam.GetPoint()->nContent.GetIndex();
2006 :
2007 0 : if( m_aFlags.bWithRedlining )
2008 : {
2009 0 : m_aNdIdx = m_aDelPam.GetPoint()->nNode;
2010 0 : m_pCurTxtNd = m_aNdIdx.GetNode().GetTxtNode();
2011 0 : pTxt = &m_pCurTxtNd->GetTxt();
2012 0 : m_aDelPam.SetMark();
2013 0 : m_aDelPam.DeleteMark();
2014 : }
2015 :
2016 0 : continue; // do not check further
2017 : }
2018 :
2019 : LanguageType eLang = bGetLanguage
2020 0 : ? m_pCurTxtNd->GetLang( nSttPos )
2021 0 : : LANGUAGE_SYSTEM;
2022 :
2023 0 : if ( m_aFlags.bAddNonBrkSpace )
2024 : {
2025 0 : SetRedlineTxt( STR_AUTOFMTREDL_NON_BREAK_SPACE );
2026 0 : pATst->FnAddNonBrkSpace( aACorrDoc, *pTxt, nSttPos, nPos, eLang );
2027 : }
2028 :
2029 0 : if( ( m_aFlags.bChgOrdinalNumber &&
2030 0 : SetRedlineTxt( STR_AUTOFMTREDL_ORDINAL ) &&
2031 0 : pATst->FnChgOrdinalNumber( aACorrDoc, *pTxt, nSttPos, nPos, eLang ) ) ||
2032 0 : ( m_aFlags.bChgToEnEmDash &&
2033 0 : SetRedlineTxt( STR_AUTOFMTREDL_DASH ) &&
2034 0 : pATst->FnChgToEnEmDash( aACorrDoc, *pTxt, nSttPos, nPos, eLang ) ) ||
2035 0 : ( m_aFlags.bSetINetAttr &&
2036 0 : (nPos == pTxt->getLength() || IsSpace((*pTxt)[nPos])) &&
2037 0 : SetRedlineTxt( STR_AUTOFMTREDL_DETECT_URL ) &&
2038 0 : pATst->FnSetINetAttr( aACorrDoc, *pTxt, nLastBlank, nPos, eLang ) ) )
2039 0 : nPos = m_aDelPam.GetPoint()->nContent.GetIndex();
2040 : else
2041 : {
2042 : // two capital letters at the beginning of a word?
2043 0 : if( m_aFlags.bCptlSttWrd )
2044 : {
2045 0 : SetRedlineTxt( STR_AUTOFMTREDL_CPTL_STT_WORD );
2046 0 : pATst->FnCptlSttWrd( aACorrDoc, *pTxt, nSttPos, nPos, eLang );
2047 : }
2048 : // capital letter at the beginning of a sentence?
2049 0 : if( m_aFlags.bCptlSttSntnc && bFirst )
2050 : {
2051 0 : SetRedlineTxt( STR_AUTOFMTREDL_CPTL_STT_SENT );
2052 0 : pATst->FnCptlSttSntnc( aACorrDoc, *pTxt, true, nSttPos, nPos, eLang);
2053 0 : bFirst = sal_False;
2054 : }
2055 :
2056 0 : bFirst = bFirstSent;
2057 0 : bFirstSent = sal_False;
2058 :
2059 0 : if( m_aFlags.bWithRedlining )
2060 : {
2061 0 : m_aNdIdx = m_aDelPam.GetPoint()->nNode;
2062 0 : m_pCurTxtNd = m_aNdIdx.GetNode().GetTxtNode();
2063 0 : pTxt = &m_pCurTxtNd->GetTxt();
2064 0 : m_aDelPam.SetMark();
2065 0 : m_aDelPam.DeleteMark();
2066 : }
2067 : }
2068 : }
2069 0 : } while (nPos < pTxt->getLength());
2070 0 : ClearRedlineTxt();
2071 : }
2072 :
2073 0 : SwAutoFormat::SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFmtFlags& rFlags,
2074 : SwNodeIndex* pSttNd, SwNodeIndex* pEndNd )
2075 : : m_aFlags( rFlags ),
2076 0 : m_aDelPam( pEdShell->GetDoc()->GetNodes().GetEndOfExtras() ),
2077 0 : m_aNdIdx( pEdShell->GetDoc()->GetNodes().GetEndOfExtras(), +1 ),
2078 0 : m_aEndNdIdx( pEdShell->GetDoc()->GetNodes().GetEndOfContent() ),
2079 : m_pEditShell( pEdShell ),
2080 0 : m_pDoc( pEdShell->GetDoc() ),
2081 : m_pCurTxtNd( 0 ), m_pCurTxtFrm( 0 ),
2082 0 : m_nRedlAutoFmtSeqId( 0 )
2083 : {
2084 : OSL_ENSURE( (pSttNd && pEndNd) || (!pSttNd && !pEndNd),
2085 : "Got no area" );
2086 :
2087 0 : if( m_aFlags.bSetNumRule && !m_aFlags.bAFmtByInput )
2088 0 : m_aFlags.bSetNumRule = false;
2089 :
2090 0 : bool bReplaceStyles = !m_aFlags.bAFmtByInput || m_aFlags.bReplaceStyles;
2091 :
2092 0 : const SwTxtNode* pNxtNd = 0;
2093 0 : bool bNxtEmpty = false;
2094 0 : sal_Bool bNxtAlpha = sal_False;
2095 0 : sal_uInt16 nNxtLevel = 0;
2096 :
2097 : // set area for autoformatting
2098 0 : if( pSttNd )
2099 : {
2100 0 : m_aNdIdx = *pSttNd;
2101 0 : m_aNdIdx--; // for GoNextPara, one paragraph prior to that
2102 0 : m_aEndNdIdx = *pEndNd;
2103 0 : m_aEndNdIdx++;
2104 :
2105 : // check the previous TextNode
2106 0 : pNxtNd = m_aNdIdx.GetNode().GetTxtNode();
2107 0 : m_bEmptyLine = !pNxtNd ||
2108 0 : IsEmptyLine( *pNxtNd ) ||
2109 0 : IsNoAlphaLine( *pNxtNd );
2110 : }
2111 : else
2112 0 : m_bEmptyLine = true; // at document beginning
2113 :
2114 0 : m_bEnd = false;
2115 :
2116 : // set value for percentage display
2117 0 : m_nEndNdIdx = m_aEndNdIdx.GetIndex();
2118 :
2119 0 : if( !m_aFlags.bAFmtByInput )
2120 0 : ::StartProgress( STR_STATSTR_AUTOFORMAT, m_aNdIdx.GetIndex(),
2121 0 : m_nEndNdIdx = m_aEndNdIdx.GetIndex(),
2122 0 : m_pDoc->GetDocShell() );
2123 :
2124 0 : RedlineMode_t eRedlMode = m_pDoc->GetRedlineMode(), eOldMode = eRedlMode;
2125 0 : if( m_aFlags.bWithRedlining )
2126 : {
2127 0 : m_pDoc->SetAutoFmtRedline( true );
2128 0 : eRedlMode = (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT);
2129 : }
2130 : else
2131 0 : eRedlMode = (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_IGNORE);
2132 0 : m_pDoc->SetRedlineMode( eRedlMode );
2133 :
2134 : // save undo state (might be turned off)
2135 0 : bool const bUndoState = m_pDoc->GetIDocumentUndoRedo().DoesUndo();
2136 :
2137 : // If multiple lines, then do not merge with next paragraph
2138 0 : m_bMoreLines = false;
2139 :
2140 0 : m_nLastCalcHeadLvl = 0;
2141 0 : m_nLastHeadLvl = USHRT_MAX;
2142 0 : sal_uInt16 nLevel = 0;
2143 0 : sal_uInt16 nDigitLvl = 0;
2144 :
2145 : // set defaults
2146 0 : SwTxtFrmInfo aFInfo( 0 );
2147 :
2148 : // This is the automat for autoformatting
2149 0 : m_eStat = READ_NEXT_PARA;
2150 0 : while( !m_bEnd )
2151 : {
2152 0 : switch( m_eStat )
2153 : {
2154 : case READ_NEXT_PARA:
2155 : {
2156 0 : GoNextPara();
2157 0 : m_eStat = m_bEnd ? IS_END : TST_EMPTY_LINE;
2158 : }
2159 0 : break;
2160 :
2161 : case TST_EMPTY_LINE:
2162 0 : if( IsEmptyLine( *m_pCurTxtNd ) )
2163 : {
2164 0 : if( m_aFlags.bDelEmptyNode && !HasObjects( *m_pCurTxtNd ) )
2165 : {
2166 0 : m_bEmptyLine = true;
2167 0 : sal_uLong nOldCnt = m_pDoc->GetNodes().Count();
2168 0 : DelEmptyLine();
2169 : // Was there really a deletion of a node?
2170 0 : if( nOldCnt != m_pDoc->GetNodes().Count() )
2171 0 : m_aNdIdx--; // do not skip the next paragraph
2172 : }
2173 0 : m_eStat = READ_NEXT_PARA;
2174 : }
2175 : else
2176 0 : m_eStat = TST_ALPHA_LINE;
2177 0 : break;
2178 :
2179 : case TST_ALPHA_LINE:
2180 0 : if( IsNoAlphaLine( *m_pCurTxtNd ))
2181 : {
2182 : // recognize a table definition +---+---+
2183 0 : if( m_aFlags.bAFmtByInput && m_aFlags.bCreateTable && DoTable() )
2184 : {
2185 : //JP 30.09.96: DoTable() builds on PopCrsr and MoveCrsr after AutoFormat!
2186 0 : pEdShell->Pop( sal_False );
2187 0 : *pEdShell->GetCrsr() = m_aDelPam;
2188 0 : pEdShell->Push();
2189 :
2190 0 : m_eStat = IS_END;
2191 0 : break;
2192 : }
2193 :
2194 : // Check for 3 "---" or "===". In this case, the previous paragraph should be
2195 : // underlined and the current be deleted!
2196 0 : if( !DoUnderline() && bReplaceStyles )
2197 : {
2198 0 : SetColl( RES_POOLCOLL_STANDARD, true );
2199 0 : m_bEmptyLine = true;
2200 : }
2201 0 : m_eStat = READ_NEXT_PARA;
2202 : }
2203 : else
2204 0 : m_eStat = GET_ALL_INFO;
2205 0 : break;
2206 :
2207 : case GET_ALL_INFO:
2208 : {
2209 0 : if( m_pCurTxtNd->GetNumRule() )
2210 : {
2211 : // do nothing in numbering, go to next
2212 0 : m_bEmptyLine = false;
2213 0 : m_eStat = READ_NEXT_PARA;
2214 : // delete all blanks at beginning/end and in between
2215 : //JP 29.04.98: first only "all in between"
2216 0 : DelMoreLinesBlanks( false );
2217 0 : break;
2218 : }
2219 :
2220 0 : aFInfo.SetFrm( m_pCurTxtFrm );
2221 :
2222 : // so far: if there were templates assigned, keep these and go to next node
2223 0 : sal_uInt16 nPoolId = m_pCurTxtNd->GetTxtColl()->GetPoolFmtId();
2224 0 : if( IsPoolUserFmt( nPoolId )
2225 0 : ? !m_aFlags.bChgUserColl
2226 0 : : ( RES_POOLCOLL_STANDARD != nPoolId &&
2227 0 : ( !m_aFlags.bAFmtByInput ||
2228 0 : (RES_POOLCOLL_TEXT_MOVE != nPoolId &&
2229 : RES_POOLCOLL_TEXT != nPoolId )) ))
2230 : {
2231 0 : m_eStat = HAS_FMTCOLL;
2232 0 : break;
2233 : }
2234 :
2235 : // check for hard spaces or LRSpaces set by the template
2236 0 : if( IsPoolUserFmt( nPoolId ) ||
2237 : RES_POOLCOLL_STANDARD == nPoolId )
2238 : {
2239 : short nSz;
2240 : SvxLRSpaceItem* pLRSpace;
2241 0 : if( SFX_ITEM_SET == m_pCurTxtNd->GetSwAttrSet().
2242 : GetItemState( RES_LR_SPACE, true,
2243 0 : (const SfxPoolItem**)&pLRSpace ) &&
2244 0 : ( 0 != (nSz = pLRSpace->GetTxtFirstLineOfst()) ||
2245 0 : 0 != pLRSpace->GetTxtLeft() ) )
2246 : {
2247 : // exception: numbering/enumation can have an indentation
2248 0 : if( IsEnumericChar( *m_pCurTxtNd ))
2249 : {
2250 0 : nLevel = CalcLevel( *m_pCurTxtNd, &nDigitLvl );
2251 0 : if( nLevel >= MAXLEVEL )
2252 0 : nLevel = MAXLEVEL-1;
2253 0 : BuildEnum( nLevel, nDigitLvl );
2254 0 : m_eStat = READ_NEXT_PARA;
2255 0 : break;
2256 : }
2257 :
2258 : // never merge (maybe only indent as exception)
2259 0 : m_bMoreLines = true;
2260 :
2261 0 : if( bReplaceStyles )
2262 : {
2263 : // then use one of our templates
2264 0 : if( 0 < nSz ) // positive 1st line indentation
2265 0 : BuildIndent();
2266 0 : else if( 0 > nSz ) // negative 1st line indentation
2267 0 : BuildNegIndent( aFInfo.GetLineStart() );
2268 0 : else if( pLRSpace->GetTxtLeft() ) // is indentation
2269 0 : BuildTextIndent();
2270 : }
2271 0 : m_eStat = READ_NEXT_PARA;
2272 0 : break;
2273 : }
2274 : }
2275 :
2276 0 : nLevel = CalcLevel( *m_pCurTxtNd, &nDigitLvl );
2277 0 : m_bMoreLines = !IsOneLine( *m_pCurTxtNd );
2278 0 : pNxtNd = GetNextNode();
2279 0 : if( pNxtNd )
2280 : {
2281 0 : bNxtEmpty = IsEmptyLine( *pNxtNd );
2282 0 : bNxtAlpha = IsNoAlphaLine( *pNxtNd );
2283 0 : nNxtLevel = CalcLevel( *pNxtNd );
2284 :
2285 0 : if( !m_bEmptyLine && HasBreakAttr( *m_pCurTxtNd ) )
2286 0 : m_bEmptyLine = true;
2287 0 : if( !bNxtEmpty && HasBreakAttr( *pNxtNd ) )
2288 0 : bNxtEmpty = true;
2289 :
2290 : }
2291 : else
2292 : {
2293 0 : bNxtEmpty = false;
2294 0 : bNxtAlpha = sal_False;
2295 0 : nNxtLevel = 0;
2296 : }
2297 0 : m_eStat = !m_bMoreLines ? IS_ONE_LINE : TST_ENUMERIC;
2298 : }
2299 0 : break;
2300 :
2301 : case IS_ONE_LINE:
2302 : {
2303 0 : m_eStat = TST_ENUMERIC;
2304 0 : if( !bReplaceStyles )
2305 0 : break;
2306 :
2307 0 : OUString sClrStr( DelLeadingBlanks(m_pCurTxtNd->GetTxt()) );
2308 :
2309 0 : if( sClrStr.isEmpty() )
2310 : {
2311 0 : m_bEmptyLine = true;
2312 0 : m_eStat = READ_NEXT_PARA;
2313 0 : break; // read next paragraph
2314 : }
2315 :
2316 : // check if headline
2317 0 : if( !m_bEmptyLine || !IsFirstCharCapital( *m_pCurTxtNd ) ||
2318 0 : IsBlanksInString( *m_pCurTxtNd ) )
2319 0 : break;
2320 :
2321 0 : m_bEmptyLine = false;
2322 0 : OUString sEndClrStr( sClrStr );
2323 0 : sal_Int32 nLen = DelTrailingBlanks( sEndClrStr ).getLength();
2324 :
2325 : // not, then check if headline
2326 0 : if( ':' == sEndClrStr[ nLen - 1 ] )
2327 : {
2328 : {
2329 0 : BuildHeadLine( 2 );
2330 0 : m_eStat = READ_NEXT_PARA;
2331 0 : break;
2332 : }
2333 : }
2334 0 : else if( 256 <= sEndClrStr[ nLen-1 ] ||
2335 0 : !strchr( ",.;", sEndClrStr[ nLen-1 ]) )
2336 : {
2337 0 : if( bNxtEmpty || bNxtAlpha
2338 0 : || ( pNxtNd && IsEnumericChar( *pNxtNd ))
2339 :
2340 : )
2341 : {
2342 :
2343 : // one level below?
2344 0 : if( nLevel >= MAXLEVEL )
2345 0 : nLevel = MAXLEVEL-1;
2346 :
2347 0 : if( USHRT_MAX == m_nLastHeadLvl )
2348 0 : m_nLastHeadLvl = 0;
2349 0 : else if( m_nLastCalcHeadLvl < nLevel )
2350 : {
2351 0 : if( m_nLastHeadLvl+1 < MAXLEVEL )
2352 0 : ++m_nLastHeadLvl;
2353 : }
2354 : // one level above?
2355 0 : else if( m_nLastCalcHeadLvl > nLevel )
2356 : {
2357 0 : if( m_nLastHeadLvl )
2358 0 : --m_nLastHeadLvl;
2359 : }
2360 0 : m_nLastCalcHeadLvl = nLevel;
2361 :
2362 0 : if( m_aFlags.bAFmtByInput )
2363 0 : BuildHeadLine( nLevel );
2364 : else
2365 0 : BuildHeadLine( m_nLastHeadLvl );
2366 0 : m_eStat = READ_NEXT_PARA;
2367 0 : break;
2368 : }
2369 0 : }
2370 : }
2371 0 : break;
2372 :
2373 : case TST_ENUMERIC:
2374 : {
2375 0 : m_bEmptyLine = false;
2376 0 : if( IsEnumericChar( *m_pCurTxtNd ))
2377 : {
2378 0 : if( nLevel >= MAXLEVEL )
2379 0 : nLevel = MAXLEVEL-1;
2380 0 : BuildEnum( nLevel, nDigitLvl );
2381 0 : m_eStat = READ_NEXT_PARA;
2382 : }
2383 0 : else if( bReplaceStyles )
2384 0 : m_eStat = nLevel ? TST_IDENT : TST_NEG_IDENT;
2385 : else
2386 0 : m_eStat = READ_NEXT_PARA;
2387 : }
2388 0 : break;
2389 :
2390 : case TST_IDENT:
2391 : // Spaces at the beginning, check again for indentation
2392 0 : if( m_bMoreLines && nLevel )
2393 : {
2394 0 : SwTwips nSz = aFInfo.GetFirstIndent();
2395 0 : if( 0 < nSz ) // positive 1st line indentation
2396 0 : BuildIndent();
2397 0 : else if( 0 > nSz ) // negative 1st line indentation
2398 0 : BuildNegIndent( aFInfo.GetLineStart() );
2399 : else // is indentation
2400 0 : BuildTextIndent();
2401 0 : m_eStat = READ_NEXT_PARA;
2402 : }
2403 0 : else if( nLevel && pNxtNd && !m_bEnd &&
2404 0 : !bNxtEmpty && !bNxtAlpha && !nNxtLevel &&
2405 0 : !IsEnumericChar( *pNxtNd ) )
2406 : {
2407 : // is an indentation
2408 0 : BuildIndent();
2409 0 : m_eStat = READ_NEXT_PARA;
2410 : }
2411 : else
2412 0 : m_eStat = TST_TXT_BODY;
2413 0 : break;
2414 :
2415 : case TST_NEG_IDENT:
2416 : // no spaces at the beginning, check again for negative indentation
2417 : {
2418 0 : if( m_bMoreLines && !nLevel )
2419 : {
2420 0 : SwTwips nSz = aFInfo.GetFirstIndent();
2421 0 : if( 0 < nSz ) // positive 1st line indentation
2422 0 : BuildIndent();
2423 0 : else if( 0 > nSz ) // negative 1st line indentation
2424 0 : BuildNegIndent( aFInfo.GetLineStart() );
2425 : else // is _no_ indentation
2426 0 : BuildText();
2427 0 : m_eStat = READ_NEXT_PARA;
2428 : }
2429 0 : else if( !nLevel && pNxtNd && !m_bEnd &&
2430 0 : !bNxtEmpty && !bNxtAlpha && nNxtLevel &&
2431 0 : !IsEnumericChar( *pNxtNd ) )
2432 : {
2433 : // is a negative indentation
2434 0 : BuildNegIndent( aFInfo.GetLineStart() );
2435 0 : m_eStat = READ_NEXT_PARA;
2436 : }
2437 : else
2438 0 : m_eStat = TST_TXT_BODY;
2439 : }
2440 0 : break;
2441 :
2442 : case TST_TXT_BODY:
2443 : {
2444 0 : if( m_bMoreLines )
2445 : {
2446 0 : SwTwips nSz = aFInfo.GetFirstIndent();
2447 0 : if( 0 < nSz ) // positive 1st line indentation
2448 0 : BuildIndent();
2449 0 : else if( 0 > nSz ) // negative 1st line indentation
2450 0 : BuildNegIndent( aFInfo.GetLineStart() );
2451 0 : else if( nLevel ) // is indentation
2452 0 : BuildTextIndent();
2453 : else
2454 0 : BuildText();
2455 : }
2456 0 : else if( nLevel )
2457 0 : BuildTextIndent();
2458 : else
2459 0 : BuildText();
2460 0 : m_eStat = READ_NEXT_PARA;
2461 : }
2462 0 : break;
2463 :
2464 : case HAS_FMTCOLL:
2465 : {
2466 : // so far: if there were templates assigned, keep these and go to next node
2467 0 : m_bEmptyLine = false;
2468 0 : m_eStat = READ_NEXT_PARA;
2469 : // delete all blanks at beginning/end and in between
2470 : //JP 29.04.98: first only "all in between"
2471 0 : DelMoreLinesBlanks( false );
2472 :
2473 : // handle hard attributes
2474 0 : if( m_pCurTxtNd->HasSwAttrSet() )
2475 : {
2476 : short nSz;
2477 : SvxLRSpaceItem* pLRSpace;
2478 0 : if( bReplaceStyles &&
2479 0 : SFX_ITEM_SET == m_pCurTxtNd->GetSwAttrSet().
2480 : GetItemState( RES_LR_SPACE, false,
2481 0 : (const SfxPoolItem**)&pLRSpace ) &&
2482 0 : ( 0 != (nSz = pLRSpace->GetTxtFirstLineOfst()) ||
2483 0 : 0 != pLRSpace->GetTxtLeft() ) )
2484 : {
2485 : // then use one of our templates
2486 0 : if( 0 < nSz ) // positive 1st line indentation
2487 0 : BuildIndent();
2488 0 : else if( 0 > nSz ) // negative 1st line indentation
2489 : {
2490 0 : BuildNegIndent( aFInfo.GetLineStart() );
2491 : }
2492 0 : else if( pLRSpace->GetTxtLeft() ) // is indentation
2493 0 : BuildTextIndent();
2494 : else
2495 0 : BuildText();
2496 : }
2497 : }
2498 : }
2499 0 : break;
2500 :
2501 : case IS_END:
2502 0 : m_bEnd = true;
2503 0 : break;
2504 : }
2505 : }
2506 :
2507 0 : if( m_aFlags.bWithRedlining )
2508 0 : m_pDoc->SetAutoFmtRedline( false );
2509 0 : m_pDoc->SetRedlineMode( eOldMode );
2510 :
2511 : // restore undo (in case it has been changed)
2512 0 : m_pDoc->GetIDocumentUndoRedo().DoUndo(bUndoState);
2513 :
2514 : // disable display of percentage again
2515 0 : if( !m_aFlags.bAFmtByInput )
2516 0 : ::EndProgress( m_pDoc->GetDocShell() );
2517 0 : }
2518 :
2519 0 : void SwEditShell::AutoFormat( const SvxSwAutoFmtFlags* pAFlags )
2520 : {
2521 0 : boost::scoped_ptr<SwWait> pWait;
2522 :
2523 0 : SET_CURR_SHELL( this );
2524 0 : StartAllAction();
2525 0 : StartUndo( UNDO_AUTOFORMAT );
2526 :
2527 0 : SvxSwAutoFmtFlags aAFFlags; // use default values or add params?
2528 0 : if( pAFlags )
2529 : {
2530 0 : aAFFlags = *pAFlags;
2531 0 : if( !aAFFlags.bAFmtByInput )
2532 0 : pWait.reset(new SwWait( *GetDoc()->GetDocShell(), true ));
2533 : }
2534 :
2535 0 : SwPaM* pCrsr = GetCrsr();
2536 : // There are more than one or a selection is open
2537 0 : if( pCrsr->GetNext() != pCrsr || pCrsr->HasMark() )
2538 : {
2539 0 : FOREACHPAM_START(GetCrsr())
2540 0 : if( PCURCRSR->HasMark() )
2541 : {
2542 0 : SwAutoFormat aFmt( this, aAFFlags, &PCURCRSR->Start()->nNode,
2543 0 : &PCURCRSR->End()->nNode );
2544 : }
2545 0 : FOREACHPAM_END()
2546 : }
2547 : else
2548 : {
2549 0 : SwAutoFormat aFmt( this, aAFFlags );
2550 : }
2551 :
2552 0 : EndUndo( UNDO_AUTOFORMAT );
2553 0 : EndAllAction();
2554 0 : }
2555 :
2556 0 : void SwEditShell::AutoFmtBySplitNode()
2557 : {
2558 0 : SET_CURR_SHELL( this );
2559 0 : SwPaM* pCrsr = GetCrsr();
2560 0 : if( pCrsr->GetNext() == pCrsr && pCrsr->Move( fnMoveBackward, fnGoNode ) )
2561 : {
2562 0 : StartAllAction();
2563 0 : StartUndo( UNDO_AUTOFORMAT );
2564 :
2565 0 : bool bRange = false;
2566 0 : pCrsr->SetMark();
2567 0 : SwIndex* pCntnt = &pCrsr->GetMark()->nContent;
2568 0 : if( pCntnt->GetIndex() )
2569 : {
2570 0 : *pCntnt = 0;
2571 0 : bRange = true;
2572 : }
2573 : else
2574 : {
2575 : // then go one node backwards
2576 0 : SwNodeIndex m_aNdIdx( pCrsr->GetMark()->nNode, -1 );
2577 0 : SwTxtNode* pTxtNd = m_aNdIdx.GetNode().GetTxtNode();
2578 0 : if (pTxtNd && !pTxtNd->GetTxt().isEmpty())
2579 : {
2580 0 : pCntnt->Assign( pTxtNd, 0 );
2581 0 : pCrsr->GetMark()->nNode = m_aNdIdx;
2582 0 : bRange = true;
2583 0 : }
2584 : }
2585 :
2586 0 : if( bRange )
2587 : {
2588 0 : Push(); // save cursor
2589 :
2590 0 : SvxSwAutoFmtFlags aAFFlags = *GetAutoFmtFlags(); // use default values so far
2591 :
2592 0 : SwAutoFormat aFmt( this, aAFFlags, &pCrsr->GetMark()->nNode,
2593 0 : &pCrsr->GetPoint()->nNode );
2594 :
2595 : //JP 30.09.96: DoTable() builds on PopCrsr and MoveCrsr!
2596 0 : Pop( sal_False );
2597 0 : pCrsr = GetCrsr();
2598 : }
2599 0 : pCrsr->DeleteMark();
2600 0 : pCrsr->Move( fnMoveForward, fnGoNode );
2601 :
2602 0 : EndUndo( UNDO_AUTOFORMAT );
2603 0 : EndAllAction();
2604 0 : }
2605 0 : }
2606 :
2607 0 : SvxSwAutoFmtFlags* SwEditShell::GetAutoFmtFlags()
2608 : {
2609 0 : if (!pAutoFmtFlags)
2610 0 : pAutoFmtFlags = new SvxSwAutoFmtFlags;
2611 :
2612 0 : return pAutoFmtFlags;
2613 : }
2614 :
2615 0 : void SwEditShell::SetAutoFmtFlags(SvxSwAutoFmtFlags * pFlags)
2616 : {
2617 0 : SvxSwAutoFmtFlags* pEditFlags = GetAutoFmtFlags();
2618 :
2619 0 : pEditFlags->bSetNumRule = pFlags->bSetNumRule;
2620 0 : pEditFlags->bChgEnumNum = pFlags->bChgEnumNum;
2621 0 : pEditFlags->bSetBorder = pFlags->bSetBorder;
2622 0 : pEditFlags->bCreateTable = pFlags->bCreateTable;
2623 0 : pEditFlags->bReplaceStyles = pFlags->bReplaceStyles;
2624 : pEditFlags->bAFmtByInpDelSpacesAtSttEnd =
2625 0 : pFlags->bAFmtByInpDelSpacesAtSttEnd;
2626 : pEditFlags->bAFmtByInpDelSpacesBetweenLines =
2627 0 : pFlags->bAFmtByInpDelSpacesBetweenLines;
2628 :
2629 : //JP 15.12.98: copy BulletChar and Font into "normal" ones
2630 : // because AutoFormat can only work with the latter!
2631 0 : pEditFlags->cBullet = pFlags->cByInputBullet;
2632 0 : pEditFlags->aBulletFont = pFlags->aByInputBulletFont;
2633 0 : pEditFlags->cByInputBullet = pFlags->cByInputBullet;
2634 0 : pEditFlags->aByInputBulletFont = pFlags->aByInputBulletFont;
2635 0 : }
2636 :
2637 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|