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 : SvxSwAutoFormatFlags* SwEditShell::s_pAutoFormatFlags = nullptr;
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 : SvxSwAutoFormatFlags 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 : SwTextNode* m_pCurTextNd; // the current TextNode
100 : SwTextFrm* m_pCurTextFrm; // 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_nRedlAutoFormatSeqId;
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 : static bool IsSpace( const sal_Unicode c )
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 : // TextNode methods
158 : const SwTextNode* GetNextNode() const;
159 0 : static bool IsEmptyLine( const SwTextNode& rNd )
160 0 : { return rNd.GetText().isEmpty() ||
161 0 : rNd.GetText().getLength() == GetLeadingBlanks( rNd.GetText() ); }
162 :
163 : bool IsOneLine( const SwTextNode& ) const;
164 : bool IsFastFullLine( const SwTextNode& ) const;
165 : bool IsNoAlphaLine( const SwTextNode&) const;
166 : bool IsEnumericChar( const SwTextNode&) const;
167 : static bool IsBlanksInString( const SwTextNode&);
168 : sal_uInt16 CalcLevel( const SwTextNode&, sal_uInt16 *pDigitLvl = 0 ) const;
169 : sal_Int32 GetBigIndent( sal_Int32& rAktSpacePos ) const;
170 :
171 : static OUString DelLeadingBlanks(const OUString& rStr);
172 : static OUString DelTrailingBlanks( const OUString& rStr );
173 : static sal_Int32 GetLeadingBlanks( const OUString& rStr );
174 : static sal_Int32 GetTrailingBlanks( const OUString& rStr );
175 :
176 : bool IsFirstCharCapital( const SwTextNode& rNd ) const;
177 : sal_uInt16 GetDigitLevel( const SwTextNode& rTextNd, sal_Int32& rPos,
178 : OUString* pPrefix = 0, OUString* pPostfix = 0,
179 : OUString* pNumTypes = 0 ) const;
180 : /// get the FORMATED TextFrame
181 : SwTextFrm* GetFrm( const SwTextNode& rTextNd ) 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 : static bool HasSelBlanks( SwPaM& rPam );
191 : static bool HasBreakAttr( const SwTextNode& );
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 SwTextNode* pTextNd ) const
206 : {
207 0 : return !m_bEnd && pTextNd &&
208 0 : !IsEmptyLine( *pTextNd ) &&
209 0 : !IsNoAlphaLine( *pTextNd) &&
210 0 : !IsEnumericChar( *pTextNd ) &&
211 0 : ((COMPLETE_STRING - 50 - pTextNd->GetText().getLength()) >
212 0 : m_pCurTextNd->GetText().getLength()) &&
213 0 : !HasBreakAttr( *pTextNd );
214 : }
215 :
216 : /// is a dot at the end ??
217 : static bool IsSentenceAtEnd( const SwTextNode& rTextNd );
218 :
219 : bool DoUnderline();
220 : bool DoTable();
221 :
222 : void _SetRedlineText( sal_uInt16 nId );
223 0 : bool SetRedlineText( sal_uInt16 nId )
224 0 : { if( m_aFlags.bWithRedlining ) _SetRedlineText( nId ); return true; }
225 0 : bool ClearRedlineText()
226 0 : { if( m_aFlags.bWithRedlining ) m_pDoc->GetDocumentRedlineManager().SetAutoFormatRedlineComment(0); return true; }
227 :
228 : public:
229 : SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFormatFlags& 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 : SwTextFrm* SwAutoFormat::GetFrm( const SwTextNode& rTextNd ) const
241 : {
242 : // get the Frame
243 0 : const SwContentFrm *pFrm = rTextNd.getLayoutFrm( m_pEditShell->GetLayout() );
244 : OSL_ENSURE( pFrm, "For Autoformat a Layout is needed" );
245 0 : if( m_aFlags.bAFormatByInput && !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->IsTextFrm() && !const_cast<SwTextFrm*>(static_cast<const SwTextFrm*>(pFrm))->Paint().IsEmpty() ) )
252 0 : pFrm->SetCompletePaint();
253 : }
254 0 : return const_cast<SwTextFrm*>(static_cast<const SwTextFrm*>(pFrm))->GetFormatted();
255 : }
256 :
257 0 : void SwAutoFormat::_SetRedlineText( sal_uInt16 nActionId )
258 : {
259 0 : OUString sText;
260 0 : sal_uInt16 nSeqNo = 0;
261 0 : if( STR_AUTOFMTREDL_END > nActionId )
262 : {
263 0 : sText = SwViewShell::GetShellRes()->GetAutoFormatNameLst()[ 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_nRedlAutoFormatSeqId;
281 0 : break;
282 : }
283 : }
284 : #if OSL_DEBUG_LEVEL > 0
285 : else
286 : sText = "Action text is missing";
287 : #endif
288 :
289 0 : m_pDoc->GetDocumentRedlineManager().SetAutoFormatRedlineComment( &sText, 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 : // NoTextNode : 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->IsTextNode() );
330 :
331 0 : if( !m_aFlags.bAFormatByInput )
332 0 : ::SetProgressState( m_aNdIdx.GetIndex() + m_nEndNdIdx - m_aEndNdIdx.GetIndex(),
333 0 : m_pDoc->GetDocShell() );
334 :
335 0 : m_pCurTextNd = static_cast<SwTextNode*>(pNewNd);
336 0 : m_pCurTextFrm = GetFrm( *m_pCurTextNd );
337 0 : return m_pCurTextNd->GetText();
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 SwFrameFormats& rFormats = *m_pDoc->GetSpzFrameFormats();
346 0 : for( auto pFrameFormat : rFormats )
347 : {
348 0 : const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
349 0 : if ((FLY_AT_PAGE != rAnchor.GetAnchorId()) &&
350 0 : rAnchor.GetContentAnchor() &&
351 0 : &rAnchor.GetContentAnchor()->nNode.GetNode() == &rNd )
352 : {
353 0 : bRet = true;
354 0 : break;
355 : }
356 : }
357 0 : return bRet;
358 : }
359 :
360 0 : const SwTextNode* 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 ]->GetTextNode();
365 : }
366 :
367 0 : bool SwAutoFormat::IsOneLine( const SwTextNode& rNd ) const
368 : {
369 0 : SwTextFrmInfo aFInfo( GetFrm( rNd ) );
370 0 : return aFInfo.IsOneLine();
371 : }
372 :
373 0 : bool SwAutoFormat::IsFastFullLine( const SwTextNode& rNd ) const
374 : {
375 0 : bool bRet = m_aFlags.bRightMargin;
376 0 : if( bRet )
377 : {
378 0 : SwTextFrmInfo aFInfo( GetFrm( rNd ) );
379 0 : bRet = aFInfo.IsFilled( m_aFlags.nRightMargin );
380 : }
381 0 : return bRet;
382 : }
383 :
384 0 : bool SwAutoFormat::IsEnumericChar( const SwTextNode& rNd ) const
385 : {
386 0 : const OUString& rText = rNd.GetText();
387 0 : sal_Int32 nBlnks = GetLeadingBlanks( rText );
388 0 : const sal_Int32 nLen = rText.getLength() - nBlnks;
389 0 : if( !nLen )
390 0 : return false;
391 :
392 : // -, +, * separated by blank ??
393 0 : if (2 < nLen && IsSpace(rText[nBlnks + 1]))
394 : {
395 0 : if (StrChr(pBulletChar, rText[nBlnks]))
396 0 : return true;
397 : // Should there be a symbol font at the position?
398 0 : SwTextFrmInfo 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 SwTextNode& rNd )
408 : {
409 : // Search more than 5 consecutive blanks/tabs in the string.
410 0 : OUString sTmp( DelLeadingBlanks(rNd.GetText()) );
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 SwTextNode& rNd, sal_uInt16 *pDigitLvl ) const
430 : {
431 0 : sal_uInt16 nLvl = 0, nBlnk = 0;
432 0 : const OUString& rText = rNd.GetText();
433 0 : if( pDigitLvl )
434 0 : *pDigitLvl = USHRT_MAX;
435 :
436 0 : if( RES_POOLCOLL_TEXT_MOVE == rNd.GetTextColl()->GetPoolFormatId() )
437 : {
438 0 : if( m_aFlags.bAFormatByInput )
439 : {
440 0 : nLvl = rNd.GetAutoFormatLvl();
441 0 : const_cast<SwTextNode&>(rNd).SetAutoFormatLvl( 0 );
442 0 : if( nLvl )
443 0 : return nLvl;
444 : }
445 0 : ++nLvl;
446 : }
447 :
448 0 : for (sal_Int32 n = 0, nEnd = rText.getLength(); n < nEnd; ++n)
449 : {
450 0 : switch (rText[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 : SwTextFrmInfo aFInfo( GetFrm( *m_pCurTextNd ) );
470 0 : const SwTextFrm* pNxtFrm = 0;
471 :
472 0 : if( !m_bMoreLines )
473 : {
474 0 : const SwTextNode* 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 SwTextNode& rNd ) const
485 : {
486 0 : const OUString& rStr = rNd.GetText();
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 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& rText(m_pCurTextNd->GetText());
511 0 : int eState = 0;
512 0 : sal_Int32 nCnt = 0;
513 0 : while (nCnt < rText.getLength())
514 : {
515 0 : int eTmp = 0;
516 0 : switch (rText[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, SvxBoxItemLine::BOTTOM );
576 0 : aBox.SetDistance( 42 ); // ~0,75 mm
577 0 : aSet.Put(aBox);
578 0 : m_pDoc->getIDocumentContentOperations().InsertItemSet( m_aDelPam, aSet );
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.bAFormatByInput ||
588 0 : m_pCurTextNd->FindTableNode() )
589 0 : return false;
590 :
591 0 : const OUString& rTmp = m_pCurTextNd->GetText();
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 : SwTextFrmInfo aInfo( m_pCurTextFrm );
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_pCurTextNd->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_pCurTextFrm->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 )
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( const OUString& rStr )
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 : return rStr.copy( 0, n+1 );
684 0 : return rStr;
685 : }
686 :
687 0 : sal_Int32 SwAutoFormat::GetLeadingBlanks( const OUString& rStr )
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 )
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 SwTextNode& rNd ) const
709 : {
710 0 : const OUString& rText = rNd.GetText();
711 0 : for( sal_Int32 n = 0, nEnd = rText.getLength(); n < nEnd; ++n )
712 0 : if (!IsSpace(rText[n]))
713 : {
714 0 : CharClass& rCC = GetCharClass( rNd.GetSwAttrSet().
715 0 : GetLanguage().GetLanguage() );
716 0 : sal_Int32 nCharType = rCC.getCharacterType( rText, 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 SwTextNode& 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& rText = rNd.GetText();
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 < rText.getLength() && nDigitLvl < MAXLEVEL - 1)
741 : {
742 0 : const sal_Unicode cCurrentChar = rText[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( rText, nPos ) )
775 : {
776 : bool bIsUpper =
777 0 : 0 != ( i18n::KCharacterType::UPPER &
778 0 : rCC.getCharacterType( rText, nPos ));
779 0 : sal_Unicode cLow = rCC.lowercase(rText, 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(rText[nPos]);
931 0 : else if( pPostfix )
932 0 : *pPostfix += OUString(rText[nPos]);
933 :
934 0 : if( NO_DELIM & eScan )
935 : {
936 0 : eScan |= CHG;
937 0 : if( pPrefix )
938 0 : *pPrefix += "\x01" + 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 == rText.getLength() || !IsSpace(rText[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 += "\x01" + 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_pCurTextNd, 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_pCurTextNd->HasSwAttrSet() )
976 : {
977 0 : aSet.Put( *m_pCurTextNd->GetpSwAttrSet() );
978 : // take HeaderLine/TextBody only if centered or right aligned, otherwise only justification
979 : SvxAdjustItem const * pAdj;
980 0 : if( SfxItemState::SET == aSet.GetItemState( RES_PARATR_ADJUST,
981 0 : false, reinterpret_cast<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->SetTextFormatCollByAutoFormat( *m_aDelPam.GetPoint(), nId, &aSet );
992 0 : }
993 :
994 0 : bool SwAutoFormat::HasSelBlanks( SwPaM& rPam )
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 : SwTextNode* pTextNd = pPos->nNode.GetNode().GetTextNode();
1001 0 : if (nBlnkPos && nBlnkPos-- < pTextNd->GetText().getLength() &&
1002 0 : (' ' == pTextNd->GetText()[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 : pTextNd = pPos->nNode.GetNode().GetTextNode();
1009 0 : if (nBlnkPos < pTextNd->GetText().getLength() &&
1010 0 : (' ' == pTextNd->GetText()[nBlnkPos]))
1011 0 : ++pPos->nContent;
1012 : else
1013 0 : return false;
1014 : }
1015 0 : return true;
1016 : }
1017 :
1018 0 : bool SwAutoFormat::HasBreakAttr( const SwTextNode& rTextNd )
1019 : {
1020 0 : const SfxItemSet* pSet = rTextNd.GetpSwAttrSet();
1021 0 : if( !pSet )
1022 0 : return false;
1023 :
1024 : const SfxPoolItem* pItem;
1025 0 : if( SfxItemState::SET == pSet->GetItemState( RES_BREAK, false, &pItem )
1026 0 : && SVX_BREAK_NONE != static_cast<const SvxFormatBreakItem*>(pItem)->GetBreak() )
1027 0 : return true;
1028 :
1029 0 : if( SfxItemState::SET == pSet->GetItemState( RES_PAGEDESC, false, &pItem )
1030 0 : && static_cast<const SwFormatPageDesc*>(pItem)->GetPageDesc()
1031 0 : && nsUseOnPage::PD_NONE != static_cast<const SwFormatPageDesc*>(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 SwTextNode& rTextNd )
1038 : {
1039 0 : const OUString& rStr = rTextNd.GetText();
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.bAFormatByInput
1053 : ? m_aFlags.bAFormatByInpDelSpacesAtSttEnd
1054 : : m_aFlags.bAFormatDelSpacesAtSttEnd )
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_pCurTextNd->GetText() )))
1061 : {
1062 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTextNd, 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_pCurTextNd->GetText().getLength() !=
1069 0 : ( nPos = GetTrailingBlanks( m_pCurTextNd->GetText() )) )
1070 : {
1071 0 : m_aDelPam.GetPoint()->nContent.Assign(
1072 0 : m_pCurTextNd, m_pCurTextNd->GetText().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_pCurTextNd, 0, pShCrsr );
1088 :
1089 0 : SwPaM* pPrev = rDelPam.GetPrev();
1090 0 : rDelPam.GetRingContainer().merge( pShCrsr->GetRingContainer() );
1091 :
1092 0 : m_pEditShell->DeleteSel( rDelPam );
1093 :
1094 : // and remove Pam again:
1095 : SwPaM* p;
1096 0 : SwPaM* pNext = &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_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
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_pCurTextNd,
1116 0 : GetTrailingBlanks( m_pCurTextNd->GetText() ) );
1117 0 : m_aDelPam.SetMark();
1118 :
1119 0 : ++m_aDelPam.GetPoint()->nNode;
1120 0 : SwTextNode* pTNd = m_aDelPam.GetNode().GetTextNode();
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_pCurTextNd->GetText().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 : SetRedlineText( 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_pCurTextNd, m_pCurTextNd->GetText().getLength() );
1150 0 : m_aDelPam.SetMark();
1151 :
1152 0 : --m_aDelPam.GetMark()->nNode;
1153 0 : SwTextNode* pTNd = m_aDelPam.GetNode( false ).GetTextNode();
1154 0 : if( pTNd )
1155 : // first use the previous text node
1156 0 : m_aDelPam.GetMark()->nContent.Assign(pTNd, pTNd->GetText().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 ).GetTextNode();
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_pCurTextNd;
1173 : }
1174 0 : if( pTNd )
1175 0 : DeleteSel( m_aDelPam );
1176 :
1177 0 : m_aDelPam.DeleteMark();
1178 0 : ClearRedlineText();
1179 0 : }
1180 :
1181 0 : void SwAutoFormat::DelMoreLinesBlanks( bool bWithLineBreaks )
1182 : {
1183 0 : if( m_aFlags.bAFormatByInput
1184 : ? m_aFlags.bAFormatByInpDelSpacesBetweenLines
1185 : : m_aFlags.bAFormatDelSpacesBetweenLines )
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_pCurTextNd, 0 );
1191 :
1192 0 : SwTextFrmInfo aFInfo( m_pCurTextFrm );
1193 0 : aFInfo.GetSpaces( m_aDelPam, !m_aFlags.bAFormatByInput || bWithLineBreaks );
1194 :
1195 : do {
1196 0 : SwPaM* pNxt = 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->getIDocumentContentOperations().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_pCurTextNd, 0 );
1222 0 : m_aDelPam.SetMark();
1223 :
1224 0 : --m_aDelPam.GetPoint()->nNode;
1225 0 : SwTextNode* pTNd = m_aDelPam.GetNode().GetTextNode();
1226 0 : if( pTNd )
1227 : {
1228 : // use the previous text node first
1229 0 : m_aDelPam.GetPoint()->nContent.Assign(pTNd, pTNd->GetText().getLength());
1230 0 : DeleteSel( m_aDelPam );
1231 : }
1232 0 : m_aDelPam.DeleteMark();
1233 0 : }
1234 :
1235 0 : void SwAutoFormat::BuildIndent()
1236 : {
1237 0 : SetRedlineText( 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_pCurTextNd ) ||
1245 0 : IsBlanksInString( *m_pCurTextNd ) ||
1246 0 : IsSentenceAtEnd( *m_pCurTextNd );
1247 0 : SetColl( RES_POOLCOLL_TEXT_IDENT );
1248 0 : if( !bBreak )
1249 : {
1250 0 : SetRedlineText( STR_AUTOFMTREDL_DEL_MORELINES );
1251 0 : const SwTextNode* 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->GetText() ))
1259 : {
1260 0 : m_pDoc->getIDocumentContentOperations().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 : SetRedlineText( 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_pCurTextNd ) ||
1282 0 : IsBlanksInString( *m_pCurTextNd ) ||
1283 0 : IsSentenceAtEnd( *m_pCurTextNd );
1284 :
1285 0 : if( m_aFlags.bAFormatByInput )
1286 0 : m_pCurTextNd->SetAutoFormatLvl( (sal_uInt8)CalcLevel( *m_pCurTextNd ) );
1287 :
1288 0 : SetColl( RES_POOLCOLL_TEXT_MOVE );
1289 0 : if( !bBreak )
1290 : {
1291 0 : SetRedlineText( STR_AUTOFMTREDL_DEL_MORELINES );
1292 0 : const SwTextNode* 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->GetText() ) )
1299 : {
1300 0 : m_pDoc->getIDocumentContentOperations().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 : SetRedlineText( 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_pCurTextNd ) ||
1320 0 : IsBlanksInString( *m_pCurTextNd ) ||
1321 0 : IsSentenceAtEnd( *m_pCurTextNd );
1322 0 : SetColl( RES_POOLCOLL_TEXT, true );
1323 0 : if( !bBreak )
1324 : {
1325 0 : SetRedlineText( STR_AUTOFMTREDL_DEL_MORELINES );
1326 0 : const SwTextNode* 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->GetText() ) )
1333 : {
1334 0 : m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, OUString(' ') );
1335 : }
1336 0 : if( bBreak )
1337 0 : break;
1338 0 : const SwTextNode* 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 : SetRedlineText( STR_AUTOFMTREDL_SET_NUMBULET );
1351 :
1352 0 : bool bBreak = true;
1353 :
1354 : // first, determine current indentation and frame width
1355 0 : SwTwips nFrmWidth = m_pCurTextFrm->Prt().Width();;
1356 : SwTwips nLeftTextPos;
1357 : {
1358 0 : sal_Int32 nPos(0);
1359 0 : while (nPos < m_pCurTextNd->GetText().getLength() &&
1360 0 : IsSpace(m_pCurTextNd->GetText()[nPos]))
1361 : {
1362 0 : ++nPos;
1363 : }
1364 :
1365 0 : SwTextFrmInfo aInfo( m_pCurTextFrm );
1366 0 : nLeftTextPos = aInfo.GetCharPos(nPos);
1367 0 : nLeftTextPos -= m_pCurTextNd->GetSwAttrSet().GetLRSpace().GetLeft();
1368 : }
1369 :
1370 0 : if( m_bMoreLines )
1371 0 : DelMoreLinesBlanks();
1372 : else
1373 0 : bBreak = !IsFastFullLine( *m_pCurTextNd ) ||
1374 0 : IsBlanksInString( *m_pCurTextNd ) ||
1375 0 : IsSentenceAtEnd( *m_pCurTextNd );
1376 0 : 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_pCurTextNd->GetNumRule()) )
1389 0 : aRule = *pCur;
1390 :
1391 : // replace bullet character with defined one
1392 0 : const OUString& rStr = m_pCurTextNd->GetText();
1393 0 : sal_Int32 nTextStt = 0;
1394 : const sal_Unicode* pFndBulletChr;
1395 0 : if( m_aFlags.bChgEnumNum &&
1396 0 : 2 < rStr.getLength() &&
1397 0 : 0 != ( pFndBulletChr = StrChr( pBulletChar, rStr[ nTextStt ] ))
1398 0 : && IsSpace( rStr[ nTextStt + 1 ] ) )
1399 : {
1400 0 : if( m_aFlags.bAFormatByInput )
1401 : {
1402 0 : if( m_aFlags.bSetNumRule )
1403 : {
1404 0 : SwCharFormat* pCFormat = m_pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool(
1405 0 : RES_POOLCHR_BUL_LEVEL );
1406 0 : bChgBullet = true;
1407 : // Was the format already somewhere adjusted?
1408 0 : if( !aRule.GetNumFormat( nLvl ) )
1409 : {
1410 0 : int nBulletPos = pFndBulletChr - pBulletChar;
1411 : sal_Unicode cBullChar;
1412 0 : const vcl::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(nLeftTextPos / nLvl)
1434 0 : : lBullIndent;
1435 0 : for( sal_uInt8 n = 0; n < MAXLEVEL; ++n, nAbsPos = nAbsPos + nSpaceSteps )
1436 : {
1437 0 : SwNumFormat aFormat( aRule.Get( n ) );
1438 0 : aFormat.SetBulletFont( pBullFnt );
1439 0 : aFormat.SetBulletChar( cBullChar );
1440 0 : aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1441 : // #i93908# clear suffix for bullet lists
1442 0 : aFormat.SetPrefix(OUString());
1443 0 : aFormat.SetSuffix(OUString());
1444 0 : aFormat.SetFirstLineOffset( lBullFirstLineOffset );
1445 0 : aFormat.SetAbsLSpace( nAbsPos );
1446 0 : if( !aFormat.GetCharFormat() )
1447 0 : aFormat.SetCharFormat( pCFormat );
1448 0 : if( bRTL )
1449 0 : aFormat.SetNumAdjust( SVX_ADJUST_RIGHT );
1450 :
1451 0 : aRule.Set( n, aFormat );
1452 :
1453 0 : if( n == nLvl &&
1454 0 : nFrmWidth < ( nSpaceSteps * MAXLEVEL ) )
1455 0 : nSpaceSteps = static_cast<sal_uInt16>(( nFrmWidth - nLeftTextPos ) /
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_pCurTextNd, nTextStt,
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 && nLeftTextPos )
1482 0 : nLvl = std::min( sal_uInt16( nLeftTextPos / 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 0 : SwCharFormat* pCFormat = m_pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool(
1493 0 : RES_POOLCHR_NUM_LEVEL );
1494 0 : if( !nDigitLevel )
1495 : {
1496 0 : SwNumFormat aFormat( aRule.Get( nLvl ) );
1497 : aFormat.SetStart( static_cast<sal_uInt16>(aPrefix.getToken( 1,
1498 0 : (sal_Unicode)1 ).toInt32()));
1499 0 : aFormat.SetPrefix( aPrefix.getToken( 0, (sal_Unicode)1 ));
1500 0 : aFormat.SetSuffix( aPostfix.getToken( 0, (sal_Unicode)1 ));
1501 0 : aFormat.SetIncludeUpperLevels( 0 );
1502 :
1503 0 : if( !aFormat.GetCharFormat() )
1504 0 : aFormat.SetCharFormat( pCFormat );
1505 :
1506 0 : if( !aNumTypes.isEmpty() )
1507 0 : aFormat.SetNumberingType(aNumTypes[ 0 ] - '0');
1508 :
1509 0 : if( bRTL )
1510 0 : aFormat.SetNumAdjust( SVX_ADJUST_RIGHT );
1511 0 : aRule.Set( nLvl, aFormat );
1512 : }
1513 : else
1514 : {
1515 0 : sal_uInt16 nSpaceSteps = nLvl ? sal_uInt16(nLeftTextPos / nLvl) : 0;
1516 : sal_uInt8 n;
1517 0 : for( n = 0; n <= nLvl; ++n )
1518 : {
1519 0 : SwNumFormat aFormat( aRule.Get( n ) );
1520 :
1521 : aFormat.SetStart( static_cast<sal_uInt16>(aPrefix.getToken( n+1,
1522 0 : (sal_Unicode)1 ).toInt32() ));
1523 0 : if( !n )
1524 0 : aFormat.SetPrefix( aPrefix.getToken( n, (sal_Unicode)1 ));
1525 0 : aFormat.SetSuffix( aPostfix.getToken( n, (sal_Unicode)1 ));
1526 0 : aFormat.SetIncludeUpperLevels( MAXLEVEL );
1527 0 : if( n < aNumTypes.getLength() )
1528 0 : aFormat.SetNumberingType((aNumTypes[ n ] - '0'));
1529 :
1530 : aFormat.SetAbsLSpace( sal_uInt16( nSpaceSteps * n )
1531 0 : + lNumIndent );
1532 :
1533 0 : if( !aFormat.GetCharFormat() )
1534 0 : aFormat.SetCharFormat( pCFormat );
1535 0 : if( bRTL )
1536 0 : aFormat.SetNumAdjust( SVX_ADJUST_RIGHT );
1537 :
1538 0 : aRule.Set( n, aFormat );
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 : SwNumFormat aFormat( aRule.Get( n ) );
1546 0 : aFormat.SetIncludeUpperLevels( MAXLEVEL );
1547 0 : if( bDefStep )
1548 : aFormat.SetAbsLSpace( sal_uInt16( (nLeftTextPos +
1549 0 : SwNumRule::GetNumIndent(static_cast<sal_uInt8>(n-nLvl)))));
1550 : else
1551 : aFormat.SetAbsLSpace( sal_uInt16( nSpaceSteps * n )
1552 0 : + lNumIndent );
1553 0 : aRule.Set( n, aFormat );
1554 0 : }
1555 : }
1556 0 : }
1557 : }
1558 0 : else if( !m_aFlags.bAFormatByInput )
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.bAFormatByInput )
1572 : {
1573 0 : m_aDelPam.SetMark();
1574 0 : ++m_aDelPam.GetMark()->nNode;
1575 0 : m_aDelPam.GetNode(false).GetTextNode()->SetAttrListLevel( nLvl );
1576 : }
1577 :
1578 0 : m_pCurTextNd->SetAttrListLevel(nLvl);
1579 0 : m_pCurTextNd->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_pCurTextNd, 0 );
1586 : }
1587 : else
1588 0 : m_aDelPam.GetPoint()->nContent.Assign( m_pCurTextNd,
1589 0 : bChgEnum ? nTextStt : 0 );
1590 0 : m_aDelPam.SetMark();
1591 :
1592 0 : if ( bChgBullet )
1593 0 : nTextStt += 2;
1594 :
1595 0 : while( nTextStt < rStr.getLength() && IsSpace( rStr[ nTextStt ] ))
1596 0 : nTextStt++;
1597 :
1598 0 : m_aDelPam.GetPoint()->nContent = nTextStt;
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->getIDocumentContentOperations().InsertString( m_aDelPam, sChgStr );
1607 :
1608 0 : SfxItemSet aSet( m_pDoc->GetAttrPool(), aTextNodeSetRange );
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->SetFormatItemByAutoFormat( 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->SetFormatItemByAutoFormat( 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 SwTextNode* pNxtNd = GetNextNode();
1640 0 : while( CanJoin( pNxtNd ) &&
1641 0 : nLvl == CalcLevel( *pNxtNd ) )
1642 : {
1643 0 : SetRedlineText( STR_AUTOFMTREDL_DEL_MORELINES );
1644 0 : bBreak = !IsFastFullLine( *pNxtNd ) || IsBlanksInString( *pNxtNd ) ||
1645 0 : IsSentenceAtEnd( *pNxtNd );
1646 0 : if( DeleteCurNxtPara( pNxtNd->GetText() ) )
1647 : {
1648 0 : m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, OUString(' ') );
1649 : }
1650 0 : if( bBreak )
1651 0 : break;
1652 0 : const SwTextNode* 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 : SetRedlineText( 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 nTextPos = GetBigIndent( nSpacePos );
1670 0 : if( m_bMoreLines )
1671 0 : DelMoreLinesBlanks( true );
1672 : else
1673 0 : bBreak = !IsFastFullLine( *m_pCurTextNd ) ||
1674 0 : ( !nTextPos && IsBlanksInString( *m_pCurTextNd )) ||
1675 0 : IsSentenceAtEnd( *m_pCurTextNd );
1676 :
1677 : SetColl( static_cast<sal_uInt16>( nTextPos
1678 : ? RES_POOLCOLL_CONFRONTATION
1679 0 : : RES_POOLCOLL_TEXT_NEGIDENT ) );
1680 :
1681 0 : if( nTextPos )
1682 : {
1683 0 : const OUString& rStr = m_pCurTextNd->GetText();
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_pCurTextNd, 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->getIDocumentContentOperations().InsertString( m_aDelPam, OUString('\t') );
1716 : }
1717 : }
1718 : }
1719 :
1720 0 : if( !bBreak )
1721 : {
1722 0 : SetRedlineText( STR_AUTOFMTREDL_DEL_MORELINES );
1723 0 : SwTextFrmInfo aFInfo( m_pCurTextFrm );
1724 0 : const SwTextNode* 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->GetText() ) )
1734 : {
1735 0 : m_pDoc->getIDocumentContentOperations().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 sText(SwViewShell::GetShellRes()->GetAutoFormatNameLst()[
1751 0 : STR_AUTOFMTREDL_SET_TMPL_HEADLINE ] );
1752 0 : sText = sText.replaceAll( "$(ARG1)", OUString::number( nLvl + 1 ) );
1753 0 : m_pDoc->GetDocumentRedlineManager().SetAutoFormatRedlineComment( &sText );
1754 : }
1755 :
1756 0 : SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + nLvl ), true );
1757 0 : if( m_aFlags.bAFormatByInput )
1758 : {
1759 0 : SwTextFormatColl& rNxtColl = m_pCurTextNd->GetTextColl()->GetNextTextFormatColl();
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.GetContentNode(), 0 );
1769 0 : m_pDoc->SetTextFormatColl( 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.bAFormatByInput ||
1787 0 : (!m_aFlags.bAutoCorrect && !bReplaceQuote && !bReplaceSglQuote &&
1788 0 : !m_aFlags.bCapitalStartSentence && !m_aFlags.bCapitalStartWord &&
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* pText = &m_pCurTextNd->GetText();
1795 0 : if (nPos >= pText->getLength())
1796 0 : return;
1797 :
1798 0 : bool bGetLanguage = m_aFlags.bChgOrdinalNumber ||
1799 0 : m_aFlags.bChgToEnEmDash || m_aFlags.bSetINetAttr ||
1800 0 : m_aFlags.bCapitalStartWord || m_aFlags.bCapitalStartSentence ||
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_pCurTextNd, 0 );
1806 :
1807 0 : SwAutoCorrDoc aACorrDoc( *m_pEditShell, m_aDelPam );
1808 :
1809 0 : SwTextFrmInfo aFInfo( 0 );
1810 :
1811 0 : sal_Int32 nSttPos, nLastBlank = nPos;
1812 0 : bool bFirst = m_aFlags.bCapitalStartSentence, bFirstSent = bFirst;
1813 0 : sal_Unicode cChar = 0;
1814 :
1815 0 : CharClass& rAppCC = GetAppCharClass();
1816 :
1817 0 : do {
1818 0 : while (nPos < pText->getLength() && IsSpace(cChar = (*pText)[nPos]))
1819 0 : ++nPos;
1820 0 : if (nPos == pText->getLength())
1821 0 : break; // das wars
1822 :
1823 0 : if( ( ( bReplaceQuote && '\"' == cChar ) ||
1824 0 : ( bReplaceSglQuote && '\'' == cChar ) ) &&
1825 0 : (!nPos || ' ' == (*pText)[nPos-1]))
1826 : {
1827 :
1828 : // beachte: Sonderfall Symbolfonts !!!
1829 0 : if( !aFInfo.GetFrm() )
1830 0 : aFInfo.SetFrm( GetFrm( *m_pCurTextNd ) );
1831 0 : if( !aFInfo.IsBullet( nPos ))
1832 : {
1833 0 : SetRedlineText( 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->getIDocumentContentOperations().ReplaceRange( m_aDelPam, sReplace, false );
1848 :
1849 0 : if( m_aFlags.bWithRedlining )
1850 : {
1851 0 : m_aNdIdx = m_aDelPam.GetPoint()->nNode;
1852 0 : m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
1853 0 : pText = &m_pCurTextNd->GetText();
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->getIDocumentContentOperations().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((*pText)[nPos-1]))
1871 0 : nLastBlank = nPos;
1872 0 : for (nSttPos = nPos; !bBreak && nPos < pText->getLength(); ++nPos)
1873 0 : switch (cChar = (*pText)[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_pCurTextNd ) );
1882 0 : if( !aFInfo.IsBullet( nPos ))
1883 : {
1884 0 : SetRedlineText( 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->getIDocumentContentOperations().ReplaceRange( m_aDelPam, sReplace, false );
1899 :
1900 0 : if( m_aFlags.bWithRedlining )
1901 : {
1902 0 : m_aNdIdx = m_aDelPam.GetPoint()->nNode;
1903 0 : m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
1904 0 : pText = &m_pCurTextNd->GetText();
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->getIDocumentContentOperations().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_pCurTextNd ) );
1929 0 : if( !aFInfo.IsBullet( nPos ))
1930 : {
1931 : SetRedlineText( '*' == cChar
1932 : ? STR_AUTOFMTREDL_BOLD
1933 0 : : STR_AUTOFMTREDL_UNDER );
1934 :
1935 0 : sal_Unicode cBlank = nSttPos ? (*pText)[nSttPos - 1] : 0;
1936 0 : m_aDelPam.GetPoint()->nContent = nPos;
1937 :
1938 0 : if( pATst->FnChgWeightUnderl( aACorrDoc, *pText,
1939 0 : nSttPos, nPos ))
1940 : {
1941 0 : if( m_aFlags.bWithRedlining )
1942 : {
1943 0 : m_aNdIdx = m_aDelPam.GetPoint()->nNode;
1944 0 : m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
1945 0 : pText = &m_pCurTextNd->GetText();
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 pText
1951 0 : if(0 == (m_pDoc->getIDocumentRedlineAccess().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 != (*pText)[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_pCurTextNd->GetLang( nSttPos )
1965 0 : : LANGUAGE_SYSTEM;
1966 :
1967 0 : SetRedlineText( STR_AUTOFMTREDL_NON_BREAK_SPACE );
1968 0 : if ( pATst->FnAddNonBrkSpace( aACorrDoc, *pText, nSttPos, nPos, eLang ) )
1969 0 : --nPos;
1970 : }
1971 0 : break;
1972 :
1973 : case '.':
1974 : case '!':
1975 : case '?':
1976 0 : if( m_aFlags.bCapitalStartSentence )
1977 0 : bFirstSent = true;
1978 : /* fallthrough */
1979 : default:
1980 0 : if( !( rAppCC.isLetterNumeric( *pText, 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 == pText->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 : SetRedlineText( 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_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
2011 0 : pText = &m_pCurTextNd->GetText();
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_pCurTextNd->GetLang( nSttPos )
2021 0 : : LANGUAGE_SYSTEM;
2022 :
2023 0 : if ( m_aFlags.bAddNonBrkSpace )
2024 : {
2025 0 : SetRedlineText( STR_AUTOFMTREDL_NON_BREAK_SPACE );
2026 0 : pATst->FnAddNonBrkSpace( aACorrDoc, *pText, nSttPos, nPos, eLang );
2027 : }
2028 :
2029 0 : if( ( m_aFlags.bChgOrdinalNumber &&
2030 0 : SetRedlineText( STR_AUTOFMTREDL_ORDINAL ) &&
2031 0 : pATst->FnChgOrdinalNumber( aACorrDoc, *pText, nSttPos, nPos, eLang ) ) ||
2032 0 : ( m_aFlags.bChgToEnEmDash &&
2033 0 : SetRedlineText( STR_AUTOFMTREDL_DASH ) &&
2034 0 : pATst->FnChgToEnEmDash( aACorrDoc, *pText, nSttPos, nPos, eLang ) ) ||
2035 0 : ( m_aFlags.bSetINetAttr &&
2036 0 : (nPos == pText->getLength() || IsSpace((*pText)[nPos])) &&
2037 0 : SetRedlineText( STR_AUTOFMTREDL_DETECT_URL ) &&
2038 0 : pATst->FnSetINetAttr( aACorrDoc, *pText, 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.bCapitalStartWord )
2044 : {
2045 0 : SetRedlineText( STR_AUTOFMTREDL_CPTL_STT_WORD );
2046 0 : pATst->FnCapitalStartWord( aACorrDoc, *pText, nSttPos, nPos, eLang );
2047 : }
2048 : // capital letter at the beginning of a sentence?
2049 0 : if( m_aFlags.bCapitalStartSentence && bFirst )
2050 : {
2051 0 : SetRedlineText( STR_AUTOFMTREDL_CPTL_STT_SENT );
2052 0 : pATst->FnCapitalStartSentence( aACorrDoc, *pText, true, nSttPos, nPos, eLang);
2053 : }
2054 :
2055 0 : bFirst = bFirstSent;
2056 0 : bFirstSent = false;
2057 :
2058 0 : if( m_aFlags.bWithRedlining )
2059 : {
2060 0 : m_aNdIdx = m_aDelPam.GetPoint()->nNode;
2061 0 : m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
2062 0 : pText = &m_pCurTextNd->GetText();
2063 0 : m_aDelPam.SetMark();
2064 0 : m_aDelPam.DeleteMark();
2065 : }
2066 : }
2067 : }
2068 0 : } while (nPos < pText->getLength());
2069 0 : ClearRedlineText();
2070 : }
2071 :
2072 0 : SwAutoFormat::SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFormatFlags& rFlags,
2073 : SwNodeIndex* pSttNd, SwNodeIndex* pEndNd )
2074 : : m_aFlags( rFlags ),
2075 0 : m_aDelPam( pEdShell->GetDoc()->GetNodes().GetEndOfExtras() ),
2076 0 : m_aNdIdx( pEdShell->GetDoc()->GetNodes().GetEndOfExtras(), +1 ),
2077 0 : m_aEndNdIdx( pEdShell->GetDoc()->GetNodes().GetEndOfContent() ),
2078 : m_pEditShell( pEdShell ),
2079 0 : m_pDoc( pEdShell->GetDoc() ),
2080 : m_pCurTextNd( 0 ), m_pCurTextFrm( 0 ),
2081 0 : m_nRedlAutoFormatSeqId( 0 )
2082 : {
2083 : OSL_ENSURE( (pSttNd && pEndNd) || (!pSttNd && !pEndNd),
2084 : "Got no area" );
2085 :
2086 0 : if( m_aFlags.bSetNumRule && !m_aFlags.bAFormatByInput )
2087 0 : m_aFlags.bSetNumRule = false;
2088 :
2089 0 : bool bReplaceStyles = !m_aFlags.bAFormatByInput || m_aFlags.bReplaceStyles;
2090 :
2091 0 : const SwTextNode* pNxtNd = 0;
2092 0 : bool bNxtEmpty = false;
2093 0 : bool bNxtAlpha = false;
2094 0 : sal_uInt16 nNxtLevel = 0;
2095 :
2096 : // set area for autoformatting
2097 0 : if( pSttNd )
2098 : {
2099 0 : m_aNdIdx = *pSttNd;
2100 0 : --m_aNdIdx; // for GoNextPara, one paragraph prior to that
2101 0 : m_aEndNdIdx = *pEndNd;
2102 0 : ++m_aEndNdIdx;
2103 :
2104 : // check the previous TextNode
2105 0 : pNxtNd = m_aNdIdx.GetNode().GetTextNode();
2106 0 : m_bEmptyLine = !pNxtNd ||
2107 0 : IsEmptyLine( *pNxtNd ) ||
2108 0 : IsNoAlphaLine( *pNxtNd );
2109 : }
2110 : else
2111 0 : m_bEmptyLine = true; // at document beginning
2112 :
2113 0 : m_bEnd = false;
2114 :
2115 : // set value for percentage display
2116 0 : m_nEndNdIdx = m_aEndNdIdx.GetIndex();
2117 :
2118 0 : if( !m_aFlags.bAFormatByInput )
2119 0 : ::StartProgress( STR_STATSTR_AUTOFORMAT, m_aNdIdx.GetIndex(),
2120 0 : m_nEndNdIdx = m_aEndNdIdx.GetIndex(),
2121 0 : m_pDoc->GetDocShell() );
2122 :
2123 0 : RedlineMode_t eRedlMode = m_pDoc->getIDocumentRedlineAccess().GetRedlineMode(), eOldMode = eRedlMode;
2124 0 : if( m_aFlags.bWithRedlining )
2125 : {
2126 0 : m_pDoc->SetAutoFormatRedline( true );
2127 0 : eRedlMode = (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT);
2128 : }
2129 : else
2130 0 : eRedlMode = (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_IGNORE);
2131 0 : m_pDoc->getIDocumentRedlineAccess().SetRedlineMode( eRedlMode );
2132 :
2133 : // save undo state (might be turned off)
2134 0 : bool const bUndoState = m_pDoc->GetIDocumentUndoRedo().DoesUndo();
2135 :
2136 : // If multiple lines, then do not merge with next paragraph
2137 0 : m_bMoreLines = false;
2138 :
2139 0 : m_nLastCalcHeadLvl = 0;
2140 0 : m_nLastHeadLvl = USHRT_MAX;
2141 0 : sal_uInt16 nLevel = 0;
2142 0 : sal_uInt16 nDigitLvl = 0;
2143 :
2144 : // set defaults
2145 0 : SwTextFrmInfo aFInfo( 0 );
2146 :
2147 : // This is the automat for autoformatting
2148 0 : m_eStat = READ_NEXT_PARA;
2149 0 : while( !m_bEnd )
2150 : {
2151 0 : switch( m_eStat )
2152 : {
2153 : case READ_NEXT_PARA:
2154 : {
2155 0 : GoNextPara();
2156 0 : m_eStat = m_bEnd ? IS_END : TST_EMPTY_LINE;
2157 : }
2158 0 : break;
2159 :
2160 : case TST_EMPTY_LINE:
2161 0 : if( IsEmptyLine( *m_pCurTextNd ) )
2162 : {
2163 0 : if( m_aFlags.bDelEmptyNode && !HasObjects( *m_pCurTextNd ) )
2164 : {
2165 0 : m_bEmptyLine = true;
2166 0 : sal_uLong nOldCnt = m_pDoc->GetNodes().Count();
2167 0 : DelEmptyLine();
2168 : // Was there really a deletion of a node?
2169 0 : if( nOldCnt != m_pDoc->GetNodes().Count() )
2170 0 : --m_aNdIdx; // do not skip the next paragraph
2171 : }
2172 0 : m_eStat = READ_NEXT_PARA;
2173 : }
2174 : else
2175 0 : m_eStat = TST_ALPHA_LINE;
2176 0 : break;
2177 :
2178 : case TST_ALPHA_LINE:
2179 0 : if( IsNoAlphaLine( *m_pCurTextNd ))
2180 : {
2181 : // recognize a table definition +---+---+
2182 0 : if( m_aFlags.bAFormatByInput && m_aFlags.bCreateTable && DoTable() )
2183 : {
2184 : //JP 30.09.96: DoTable() builds on PopCrsr and MoveCrsr after AutoFormat!
2185 0 : pEdShell->Pop( false );
2186 0 : *pEdShell->GetCrsr() = m_aDelPam;
2187 0 : pEdShell->Push();
2188 :
2189 0 : m_eStat = IS_END;
2190 0 : break;
2191 : }
2192 :
2193 : // Check for 3 "---" or "===". In this case, the previous paragraph should be
2194 : // underlined and the current be deleted!
2195 0 : if( !DoUnderline() && bReplaceStyles )
2196 : {
2197 0 : SetColl( RES_POOLCOLL_STANDARD, true );
2198 0 : m_bEmptyLine = true;
2199 : }
2200 0 : m_eStat = READ_NEXT_PARA;
2201 : }
2202 : else
2203 0 : m_eStat = GET_ALL_INFO;
2204 0 : break;
2205 :
2206 : case GET_ALL_INFO:
2207 : {
2208 0 : if( m_pCurTextNd->GetNumRule() )
2209 : {
2210 : // do nothing in numbering, go to next
2211 0 : m_bEmptyLine = false;
2212 0 : m_eStat = READ_NEXT_PARA;
2213 : // delete all blanks at beginning/end and in between
2214 : //JP 29.04.98: first only "all in between"
2215 0 : DelMoreLinesBlanks( false );
2216 0 : break;
2217 : }
2218 :
2219 0 : aFInfo.SetFrm( m_pCurTextFrm );
2220 :
2221 : // so far: if there were templates assigned, keep these and go to next node
2222 0 : sal_uInt16 nPoolId = m_pCurTextNd->GetTextColl()->GetPoolFormatId();
2223 0 : if( IsPoolUserFormat( nPoolId )
2224 0 : ? !m_aFlags.bChgUserColl
2225 0 : : ( RES_POOLCOLL_STANDARD != nPoolId &&
2226 0 : ( !m_aFlags.bAFormatByInput ||
2227 0 : (RES_POOLCOLL_TEXT_MOVE != nPoolId &&
2228 : RES_POOLCOLL_TEXT != nPoolId )) ))
2229 : {
2230 0 : m_eStat = HAS_FMTCOLL;
2231 0 : break;
2232 : }
2233 :
2234 : // check for hard spaces or LRSpaces set by the template
2235 0 : if( IsPoolUserFormat( nPoolId ) ||
2236 : RES_POOLCOLL_STANDARD == nPoolId )
2237 : {
2238 : short nSz;
2239 : SvxLRSpaceItem const * pLRSpace;
2240 0 : if( SfxItemState::SET == m_pCurTextNd->GetSwAttrSet().
2241 : GetItemState( RES_LR_SPACE, true,
2242 0 : reinterpret_cast<const SfxPoolItem**>(&pLRSpace) ) &&
2243 0 : ( 0 != (nSz = pLRSpace->GetTextFirstLineOfst()) ||
2244 0 : 0 != pLRSpace->GetTextLeft() ) )
2245 : {
2246 : // exception: numbering/enumation can have an indentation
2247 0 : if( IsEnumericChar( *m_pCurTextNd ))
2248 : {
2249 0 : nLevel = CalcLevel( *m_pCurTextNd, &nDigitLvl );
2250 0 : if( nLevel >= MAXLEVEL )
2251 0 : nLevel = MAXLEVEL-1;
2252 0 : BuildEnum( nLevel, nDigitLvl );
2253 0 : m_eStat = READ_NEXT_PARA;
2254 0 : break;
2255 : }
2256 :
2257 : // never merge (maybe only indent as exception)
2258 0 : m_bMoreLines = true;
2259 :
2260 0 : if( bReplaceStyles )
2261 : {
2262 : // then use one of our templates
2263 0 : if( 0 < nSz ) // positive 1st line indentation
2264 0 : BuildIndent();
2265 0 : else if( 0 > nSz ) // negative 1st line indentation
2266 0 : BuildNegIndent( aFInfo.GetLineStart() );
2267 0 : else if( pLRSpace->GetTextLeft() ) // is indentation
2268 0 : BuildTextIndent();
2269 : }
2270 0 : m_eStat = READ_NEXT_PARA;
2271 0 : break;
2272 : }
2273 : }
2274 :
2275 0 : nLevel = CalcLevel( *m_pCurTextNd, &nDigitLvl );
2276 0 : m_bMoreLines = !IsOneLine( *m_pCurTextNd );
2277 0 : pNxtNd = GetNextNode();
2278 0 : if( pNxtNd )
2279 : {
2280 0 : bNxtEmpty = IsEmptyLine( *pNxtNd );
2281 0 : bNxtAlpha = IsNoAlphaLine( *pNxtNd );
2282 0 : nNxtLevel = CalcLevel( *pNxtNd );
2283 :
2284 0 : if( !m_bEmptyLine && HasBreakAttr( *m_pCurTextNd ) )
2285 0 : m_bEmptyLine = true;
2286 0 : if( !bNxtEmpty && HasBreakAttr( *pNxtNd ) )
2287 0 : bNxtEmpty = true;
2288 :
2289 : }
2290 : else
2291 : {
2292 0 : bNxtEmpty = false;
2293 0 : bNxtAlpha = false;
2294 0 : nNxtLevel = 0;
2295 : }
2296 0 : m_eStat = !m_bMoreLines ? IS_ONE_LINE : TST_ENUMERIC;
2297 : }
2298 0 : break;
2299 :
2300 : case IS_ONE_LINE:
2301 : {
2302 0 : m_eStat = TST_ENUMERIC;
2303 0 : if( !bReplaceStyles )
2304 0 : break;
2305 :
2306 0 : const OUString sClrStr( DelLeadingBlanks(m_pCurTextNd->GetText()) );
2307 :
2308 0 : if( sClrStr.isEmpty() )
2309 : {
2310 0 : m_bEmptyLine = true;
2311 0 : m_eStat = READ_NEXT_PARA;
2312 0 : break; // read next paragraph
2313 : }
2314 :
2315 : // check if headline
2316 0 : if( !m_bEmptyLine || !IsFirstCharCapital( *m_pCurTextNd ) ||
2317 0 : IsBlanksInString( *m_pCurTextNd ) )
2318 0 : break;
2319 :
2320 0 : m_bEmptyLine = false;
2321 0 : const OUString sEndClrStr( DelTrailingBlanks(sClrStr) );
2322 0 : const sal_Unicode cLast = sEndClrStr[sEndClrStr.getLength() - 1];
2323 :
2324 : // not, then check if headline
2325 0 : if( ':' == cLast )
2326 : {
2327 0 : BuildHeadLine( 2 );
2328 0 : m_eStat = READ_NEXT_PARA;
2329 0 : break;
2330 : }
2331 0 : else if( 256 <= cLast || !strchr( ",.;", cLast ) )
2332 : {
2333 0 : if( bNxtEmpty || bNxtAlpha
2334 0 : || ( pNxtNd && IsEnumericChar( *pNxtNd ))
2335 :
2336 : )
2337 : {
2338 :
2339 : // one level below?
2340 0 : if( nLevel >= MAXLEVEL )
2341 0 : nLevel = MAXLEVEL-1;
2342 :
2343 0 : if( USHRT_MAX == m_nLastHeadLvl )
2344 0 : m_nLastHeadLvl = 0;
2345 0 : else if( m_nLastCalcHeadLvl < nLevel )
2346 : {
2347 0 : if( m_nLastHeadLvl+1 < MAXLEVEL )
2348 0 : ++m_nLastHeadLvl;
2349 : }
2350 : // one level above?
2351 0 : else if( m_nLastCalcHeadLvl > nLevel )
2352 : {
2353 0 : if( m_nLastHeadLvl )
2354 0 : --m_nLastHeadLvl;
2355 : }
2356 0 : m_nLastCalcHeadLvl = nLevel;
2357 :
2358 0 : if( m_aFlags.bAFormatByInput )
2359 0 : BuildHeadLine( nLevel );
2360 : else
2361 0 : BuildHeadLine( m_nLastHeadLvl );
2362 0 : m_eStat = READ_NEXT_PARA;
2363 0 : break;
2364 : }
2365 0 : }
2366 : }
2367 0 : break;
2368 :
2369 : case TST_ENUMERIC:
2370 : {
2371 0 : m_bEmptyLine = false;
2372 0 : if( IsEnumericChar( *m_pCurTextNd ))
2373 : {
2374 0 : if( nLevel >= MAXLEVEL )
2375 0 : nLevel = MAXLEVEL-1;
2376 0 : BuildEnum( nLevel, nDigitLvl );
2377 0 : m_eStat = READ_NEXT_PARA;
2378 : }
2379 0 : else if( bReplaceStyles )
2380 0 : m_eStat = nLevel ? TST_IDENT : TST_NEG_IDENT;
2381 : else
2382 0 : m_eStat = READ_NEXT_PARA;
2383 : }
2384 0 : break;
2385 :
2386 : case TST_IDENT:
2387 : // Spaces at the beginning, check again for indentation
2388 0 : if( m_bMoreLines && nLevel )
2389 : {
2390 0 : SwTwips nSz = aFInfo.GetFirstIndent();
2391 0 : if( 0 < nSz ) // positive 1st line indentation
2392 0 : BuildIndent();
2393 0 : else if( 0 > nSz ) // negative 1st line indentation
2394 0 : BuildNegIndent( aFInfo.GetLineStart() );
2395 : else // is indentation
2396 0 : BuildTextIndent();
2397 0 : m_eStat = READ_NEXT_PARA;
2398 : }
2399 0 : else if( nLevel && pNxtNd && !m_bEnd &&
2400 0 : !bNxtEmpty && !bNxtAlpha && !nNxtLevel &&
2401 0 : !IsEnumericChar( *pNxtNd ) )
2402 : {
2403 : // is an indentation
2404 0 : BuildIndent();
2405 0 : m_eStat = READ_NEXT_PARA;
2406 : }
2407 : else
2408 0 : m_eStat = TST_TXT_BODY;
2409 0 : break;
2410 :
2411 : case TST_NEG_IDENT:
2412 : // no spaces at the beginning, check again for negative indentation
2413 : {
2414 0 : if( m_bMoreLines && !nLevel )
2415 : {
2416 0 : SwTwips nSz = aFInfo.GetFirstIndent();
2417 0 : if( 0 < nSz ) // positive 1st line indentation
2418 0 : BuildIndent();
2419 0 : else if( 0 > nSz ) // negative 1st line indentation
2420 0 : BuildNegIndent( aFInfo.GetLineStart() );
2421 : else // is _no_ indentation
2422 0 : BuildText();
2423 0 : m_eStat = READ_NEXT_PARA;
2424 : }
2425 0 : else if( !nLevel && pNxtNd && !m_bEnd &&
2426 0 : !bNxtEmpty && !bNxtAlpha && nNxtLevel &&
2427 0 : !IsEnumericChar( *pNxtNd ) )
2428 : {
2429 : // is a negative indentation
2430 0 : BuildNegIndent( aFInfo.GetLineStart() );
2431 0 : m_eStat = READ_NEXT_PARA;
2432 : }
2433 : else
2434 0 : m_eStat = TST_TXT_BODY;
2435 : }
2436 0 : break;
2437 :
2438 : case TST_TXT_BODY:
2439 : {
2440 0 : if( m_bMoreLines )
2441 : {
2442 0 : SwTwips nSz = aFInfo.GetFirstIndent();
2443 0 : if( 0 < nSz ) // positive 1st line indentation
2444 0 : BuildIndent();
2445 0 : else if( 0 > nSz ) // negative 1st line indentation
2446 0 : BuildNegIndent( aFInfo.GetLineStart() );
2447 0 : else if( nLevel ) // is indentation
2448 0 : BuildTextIndent();
2449 : else
2450 0 : BuildText();
2451 : }
2452 0 : else if( nLevel )
2453 0 : BuildTextIndent();
2454 : else
2455 0 : BuildText();
2456 0 : m_eStat = READ_NEXT_PARA;
2457 : }
2458 0 : break;
2459 :
2460 : case HAS_FMTCOLL:
2461 : {
2462 : // so far: if there were templates assigned, keep these and go to next node
2463 0 : m_bEmptyLine = false;
2464 0 : m_eStat = READ_NEXT_PARA;
2465 : // delete all blanks at beginning/end and in between
2466 : //JP 29.04.98: first only "all in between"
2467 0 : DelMoreLinesBlanks( false );
2468 :
2469 : // handle hard attributes
2470 0 : if( m_pCurTextNd->HasSwAttrSet() )
2471 : {
2472 : short nSz;
2473 : SvxLRSpaceItem const * pLRSpace;
2474 0 : if( bReplaceStyles &&
2475 0 : SfxItemState::SET == m_pCurTextNd->GetSwAttrSet().
2476 : GetItemState( RES_LR_SPACE, false,
2477 0 : reinterpret_cast<const SfxPoolItem**>(&pLRSpace) ) &&
2478 0 : ( 0 != (nSz = pLRSpace->GetTextFirstLineOfst()) ||
2479 0 : 0 != pLRSpace->GetTextLeft() ) )
2480 : {
2481 : // then use one of our templates
2482 0 : if( 0 < nSz ) // positive 1st line indentation
2483 0 : BuildIndent();
2484 0 : else if( 0 > nSz ) // negative 1st line indentation
2485 : {
2486 0 : BuildNegIndent( aFInfo.GetLineStart() );
2487 : }
2488 0 : else if( pLRSpace->GetTextLeft() ) // is indentation
2489 0 : BuildTextIndent();
2490 : else
2491 0 : BuildText();
2492 : }
2493 : }
2494 : }
2495 0 : break;
2496 :
2497 : case IS_END:
2498 0 : m_bEnd = true;
2499 0 : break;
2500 : }
2501 : }
2502 :
2503 0 : if( m_aFlags.bWithRedlining )
2504 0 : m_pDoc->SetAutoFormatRedline( false );
2505 0 : m_pDoc->getIDocumentRedlineAccess().SetRedlineMode( eOldMode );
2506 :
2507 : // restore undo (in case it has been changed)
2508 0 : m_pDoc->GetIDocumentUndoRedo().DoUndo(bUndoState);
2509 :
2510 : // disable display of percentage again
2511 0 : if( !m_aFlags.bAFormatByInput )
2512 0 : ::EndProgress( m_pDoc->GetDocShell() );
2513 0 : }
2514 :
2515 0 : void SwEditShell::AutoFormat( const SvxSwAutoFormatFlags* pAFlags )
2516 : {
2517 0 : boost::scoped_ptr<SwWait> pWait;
2518 :
2519 0 : SET_CURR_SHELL( this );
2520 0 : StartAllAction();
2521 0 : StartUndo( UNDO_AUTOFORMAT );
2522 :
2523 0 : SvxSwAutoFormatFlags aAFFlags; // use default values or add params?
2524 0 : if( pAFlags )
2525 : {
2526 0 : aAFFlags = *pAFlags;
2527 0 : if( !aAFFlags.bAFormatByInput )
2528 0 : pWait.reset(new SwWait( *GetDoc()->GetDocShell(), true ));
2529 : }
2530 :
2531 0 : SwPaM* pCrsr = GetCrsr();
2532 : // There are more than one or a selection is open
2533 0 : if( pCrsr->GetNext() != pCrsr || pCrsr->HasMark() )
2534 : {
2535 0 : for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
2536 : {
2537 0 : if( rPaM.HasMark() )
2538 : {
2539 0 : SwAutoFormat aFormat( this, aAFFlags, &(rPaM.Start()->nNode),
2540 0 : &(rPaM.End()->nNode) );
2541 : }
2542 : }
2543 : }
2544 : else
2545 : {
2546 0 : SwAutoFormat aFormat( this, aAFFlags );
2547 : }
2548 :
2549 0 : EndUndo( UNDO_AUTOFORMAT );
2550 0 : EndAllAction();
2551 0 : }
2552 :
2553 0 : void SwEditShell::AutoFormatBySplitNode()
2554 : {
2555 0 : SET_CURR_SHELL( this );
2556 0 : SwPaM* pCrsr = GetCrsr();
2557 0 : if( !pCrsr->IsMultiSelection() && pCrsr->Move( fnMoveBackward, fnGoNode ) )
2558 : {
2559 0 : StartAllAction();
2560 0 : StartUndo( UNDO_AUTOFORMAT );
2561 :
2562 0 : bool bRange = false;
2563 0 : pCrsr->SetMark();
2564 0 : SwIndex* pContent = &pCrsr->GetMark()->nContent;
2565 0 : if( pContent->GetIndex() )
2566 : {
2567 0 : *pContent = 0;
2568 0 : bRange = true;
2569 : }
2570 : else
2571 : {
2572 : // then go one node backwards
2573 0 : SwNodeIndex m_aNdIdx( pCrsr->GetMark()->nNode, -1 );
2574 0 : SwTextNode* pTextNd = m_aNdIdx.GetNode().GetTextNode();
2575 0 : if (pTextNd && !pTextNd->GetText().isEmpty())
2576 : {
2577 0 : pContent->Assign( pTextNd, 0 );
2578 0 : pCrsr->GetMark()->nNode = m_aNdIdx;
2579 0 : bRange = true;
2580 0 : }
2581 : }
2582 :
2583 0 : if( bRange )
2584 : {
2585 0 : Push(); // save cursor
2586 :
2587 0 : SvxSwAutoFormatFlags aAFFlags = *GetAutoFormatFlags(); // use default values so far
2588 :
2589 0 : SwAutoFormat aFormat( this, aAFFlags, &pCrsr->GetMark()->nNode,
2590 0 : &pCrsr->GetPoint()->nNode );
2591 :
2592 : //JP 30.09.96: DoTable() builds on PopCrsr and MoveCrsr!
2593 0 : Pop( false );
2594 0 : pCrsr = GetCrsr();
2595 : }
2596 0 : pCrsr->DeleteMark();
2597 0 : pCrsr->Move( fnMoveForward, fnGoNode );
2598 :
2599 0 : EndUndo( UNDO_AUTOFORMAT );
2600 0 : EndAllAction();
2601 0 : }
2602 0 : }
2603 :
2604 60 : SvxSwAutoFormatFlags* SwEditShell::GetAutoFormatFlags()
2605 : {
2606 60 : if (!s_pAutoFormatFlags)
2607 59 : s_pAutoFormatFlags = new SvxSwAutoFormatFlags;
2608 :
2609 60 : return s_pAutoFormatFlags;
2610 : }
2611 :
2612 60 : void SwEditShell::SetAutoFormatFlags(SvxSwAutoFormatFlags * pFlags)
2613 : {
2614 60 : SvxSwAutoFormatFlags* pEditFlags = GetAutoFormatFlags();
2615 :
2616 60 : pEditFlags->bSetNumRule = pFlags->bSetNumRule;
2617 60 : pEditFlags->bChgEnumNum = pFlags->bChgEnumNum;
2618 60 : pEditFlags->bSetBorder = pFlags->bSetBorder;
2619 60 : pEditFlags->bCreateTable = pFlags->bCreateTable;
2620 60 : pEditFlags->bReplaceStyles = pFlags->bReplaceStyles;
2621 : pEditFlags->bAFormatByInpDelSpacesAtSttEnd =
2622 60 : pFlags->bAFormatByInpDelSpacesAtSttEnd;
2623 : pEditFlags->bAFormatByInpDelSpacesBetweenLines =
2624 60 : pFlags->bAFormatByInpDelSpacesBetweenLines;
2625 :
2626 : //JP 15.12.98: copy BulletChar and Font into "normal" ones
2627 : // because AutoFormat can only work with the latter!
2628 60 : pEditFlags->cBullet = pFlags->cByInputBullet;
2629 60 : pEditFlags->aBulletFont = pFlags->aByInputBulletFont;
2630 60 : pEditFlags->cByInputBullet = pFlags->cByInputBullet;
2631 60 : pEditFlags->aByInputBulletFont = pFlags->aByInputBulletFont;
2632 237 : }
2633 :
2634 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|