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