LibreOffice Module sw (master)  1
autofmt.cxx
Go to the documentation of this file.
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 <hintids.hxx>
21 
22 #include <unotools/charclass.hxx>
23 
24 #include <editeng/boxitem.hxx>
25 #include <editeng/lrspitem.hxx>
27 #include <editeng/adjustitem.hxx>
28 #include <editeng/tstpitem.hxx>
29 #include <editeng/fontitem.hxx>
30 #include <editeng/langitem.hxx>
31 #include <editeng/acorrcfg.hxx>
32 
33 #include <swwait.hxx>
34 #include <fmtpdsc.hxx>
35 #include <doc.hxx>
36 #include <IDocumentUndoRedo.hxx>
39 #include <redline.hxx>
40 #include <unocrsr.hxx>
41 #include <docary.hxx>
42 #include <editsh.hxx>
43 #include <index.hxx>
44 #include <pam.hxx>
45 #include <swundo.hxx>
46 #include <poolfmt.hxx>
47 #include <ndtxt.hxx>
48 #include <rootfrm.hxx>
49 #include <txtfrm.hxx>
50 #include <frminf.hxx>
51 #include <pagedesc.hxx>
52 #include <paratr.hxx>
53 #include <acorrect.hxx>
54 #include <shellres.hxx>
55 #include <section.hxx>
56 #include <frmatr.hxx>
57 #include <charatr.hxx>
58 #include <mdiexp.hxx>
59 #include <strings.hrc>
60 #include <comcore.hxx>
61 #include <numrule.hxx>
62 #include <itabenum.hxx>
63 
64 #include <memory>
65 
66 using namespace ::com::sun::star;
67 
68 //JP 16.12.99: definition:
69 // from pos cPosEnDash to cPosEmDash all chars changed to em dashes,
70 // from pos cPosEmDash to cPosEnd all chars changed to em dashes
71 // all other chars are changed to the user configuration
72 
73 const sal_Unicode pBulletChar[6] = { '+', '*', '-', 0x2013, 0x2014, 0 };
74 const int cnPosEnDash = 2, cnPosEmDash = 4;
75 
78 
80 
81 // Number of num-/bullet-paragraph templates. MAXLEVEL will soon be raised
82 // to x, but not the number of templates. (Artifact from <= 4.0)
83 const sal_uInt16 cnNumBullColls = 4;
84 
86 {
88  SwPaM m_aDelPam; // a Pam that can be used
89  SwNodeIndex m_aNdIdx; // the index on the current TextNode
90  SwNodeIndex m_aEndNdIdx; // index on the end of the area
91 
94  SwTextNode* m_pCurTextNd; // the current TextNode
95  SwTextFrame* m_pCurTextFrame; // frame of the current TextNode
96  sal_uLong m_nEndNdIdx; // for the percentage-display
97  mutable std::unique_ptr<CharClass> m_pCharClass; // Character classification
99 
101 
102  enum
103  {
104  NONE = 0,
105  DELIM = 1,
106  DIGIT = 2,
107  CHG = 4,
113  };
114 
115  bool m_bEnd : 1;
116  bool m_bMoreLines : 1;
117 
119  {
120  if( !m_pCharClass || eLang != m_eCharClassLang )
121  {
122  m_pCharClass.reset( new CharClass( LanguageTag( eLang ) ) );
123  m_eCharClassLang = eLang;
124  }
125  return *m_pCharClass;
126  }
127 
128  static bool IsSpace( const sal_Unicode c )
129  { return (' ' == c || '\t' == c || 0x0a == c|| 0x3000 == c /* Jap. space */); }
130 
131  void SetColl( sal_uInt16 nId, bool bHdLineOrText = false );
132  void GoNextPara();
133  static bool HasObjects(const SwTextFrame &);
134 
135  // TextNode methods
136  const SwTextFrame * GetNextNode(bool isCheckEnd = true) const;
137  static bool IsEmptyLine(const SwTextFrame & rFrame)
138  {
139  return rFrame.GetText().isEmpty()
140  || rFrame.GetText().getLength() == GetLeadingBlanks(rFrame.GetText());
141  }
142 
143  bool IsOneLine(const SwTextFrame &) const;
144  bool IsFastFullLine(const SwTextFrame &) const;
145  bool IsNoAlphaLine(const SwTextFrame &) const;
146  bool IsEnumericChar(const SwTextFrame &) const;
147  static bool IsBlanksInString(const SwTextFrame&);
148  sal_uInt16 CalcLevel(const SwTextFrame&, sal_uInt16 *pDigitLvl = nullptr) const;
149  sal_Int32 GetBigIndent(TextFrameIndex & rCurrentSpacePos) const;
150 
151  static OUString DelLeadingBlanks(const OUString& rStr);
152  static OUString DelTrailingBlanks( const OUString& rStr );
153  static sal_Int32 GetLeadingBlanks( const OUString& rStr );
154  static sal_Int32 GetTrailingBlanks( const OUString& rStr );
155 
156  bool IsFirstCharCapital(const SwTextFrame & rNd) const;
157  sal_uInt16 GetDigitLevel(const SwTextFrame& rFrame, TextFrameIndex& rPos,
158  OUString* pPrefix = nullptr, OUString* pPostfix = nullptr,
159  OUString* pNumTypes = nullptr ) const;
161  SwTextFrame* GetFrame( const SwTextNode& rTextNd ) const;
162  SwTextFrame * EnsureFormatted(SwTextFrame const&) const;
163 
164  void BuildIndent();
165  void BuildText();
166  void BuildTextIndent();
167  void BuildEnum( sal_uInt16 nLvl, sal_uInt16 nDigitLevel );
168  void BuildNegIndent( SwTwips nSpaces );
169  void BuildHeadLine( sal_uInt16 nLvl );
170 
171  static bool HasBreakAttr(const SwTextFrame &);
172  void DeleteSel( SwPaM& rPam );
173  void DeleteSelImpl(SwPaM & rDelPam, SwPaM & rPamToCorrect);
174  bool DeleteJoinCurNextPara(SwTextFrame const* pNextFrame, bool bIgnoreLeadingBlanks = false);
176  void DeleteLeadingTrailingBlanks( bool bStart = true, bool bEnd = true );
177  void DelEmptyLine( bool bTstNextPara = true );
180  void DelMoreLinesBlanks( bool bWithLineBreaks = false );
182  void JoinPrevPara();
184  void AutoCorrect(TextFrameIndex nSttPos = TextFrameIndex(0));
185 
186  bool CanJoin(const SwTextFrame * pNextFrame) const
187  {
188  return !m_bEnd && pNextFrame
189  && !IsEmptyLine(*pNextFrame)
190  && !IsNoAlphaLine(*pNextFrame)
191  && !IsEnumericChar(*pNextFrame)
192  // check the last / first nodes here...
193  && ((COMPLETE_STRING - 50 - pNextFrame->GetTextNodeFirst()->GetText().getLength())
194  > (m_pCurTextFrame->GetMergedPara()
195  ? m_pCurTextFrame->GetMergedPara()->pLastNode
196  : m_pCurTextNd)->GetText().getLength())
197  && !HasBreakAttr(*pNextFrame);
198  }
199 
201  static bool IsSentenceAtEnd(const SwTextFrame & rTextFrame);
202 
203  bool DoUnderline();
204  bool DoTable();
205 
206  void SetRedlineText_( sal_uInt16 nId );
207  bool SetRedlineText( sal_uInt16 nId ) {
208  if( m_aFlags.bWithRedlining )
209  SetRedlineText_( nId );
210  return true;
211  }
213  if( m_aFlags.bWithRedlining )
215  }
216 
217 public:
218  SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFormatFlags const & rFlags,
219  SwNodeIndex const * pSttNd = nullptr, SwNodeIndex const * pEndNd = nullptr );
220 };
221 
222 static const sal_Unicode* StrChr( const sal_Unicode* pSrc, sal_Unicode c )
223 {
224  while( *pSrc && *pSrc != c )
225  ++pSrc;
226  return *pSrc ? pSrc : nullptr;
227 }
228 
230 {
231  // get the Frame
232  const SwContentFrame *pFrame = rTextNd.getLayoutFrame( m_pEditShell->GetLayout() );
233  assert(pFrame && "For Autoformat a Layout is needed");
234  return EnsureFormatted(*static_cast<SwTextFrame const*>(pFrame));
235 }
236 
238 {
239  SwTextFrame *const pFrame(const_cast<SwTextFrame*>(&rFrame));
240  if( m_aFlags.bAFormatByInput && !pFrame->isFrameAreaDefinitionValid() )
241  {
243  SwRect aTmpFrame( pFrame->getFrameArea() );
244  SwRect aTmpPrt( pFrame->getFramePrintArea() );
245  pFrame->Calc(pFrame->getRootFrame()->GetCurrShell()->GetOut());
246 
247  if( pFrame->getFrameArea() != aTmpFrame || pFrame->getFramePrintArea() != aTmpPrt ||
248  !pFrame->GetPaintSwRect().IsEmpty())
249  {
250  pFrame->SetCompletePaint();
251  }
252  }
253 
254  return pFrame->GetFormatted();
255 }
256 
257 void SwAutoFormat::SetRedlineText_( sal_uInt16 nActionId )
258 {
259  OUString sText;
260  sal_uInt16 nSeqNo = 0;
261  if( STR_AUTOFMTREDL_END > nActionId )
262  {
263  sText = SwViewShell::GetShellRes()->GetAutoFormatNameLst()[ nActionId ];
264  switch( nActionId )
265  {
268 
269  // AutoCorrect actions
281  nSeqNo = ++m_nRedlAutoFormatSeqId;
282  break;
283  }
284  }
285 #if OSL_DEBUG_LEVEL > 0
286  else
287  sText = "Action text is missing";
288 #endif
289 
290  m_pDoc->GetDocumentRedlineManager().SetAutoFormatRedlineComment( &sText, nSeqNo );
291 }
292 
294 {
295  SwNode* pNewNd = nullptr;
296  do {
297  // has to be checked twice before and after incrementation
298  if( m_aNdIdx.GetIndex() >= m_aEndNdIdx.GetIndex() )
299  {
300  m_bEnd = true;
301  return;
302  }
303 
304  sw::GotoNextLayoutTextFrame(m_aNdIdx, m_pEditShell->GetLayout());
305  if( m_aNdIdx.GetIndex() >= m_aEndNdIdx.GetIndex() )
306  {
307  m_bEnd = true;
308  return;
309  }
310  else
311  pNewNd = &m_aNdIdx.GetNode();
312 
313  // not a TextNode ->
314  // TableNode : skip table
315  // NoTextNode : skip nodes
316  // EndNode : at the end, terminate
317  if( pNewNd->IsEndNode() )
318  {
319  m_bEnd = true;
320  return;
321  }
322  else if( pNewNd->IsTableNode() )
323  m_aNdIdx = *pNewNd->EndOfSectionNode();
324  else if( pNewNd->IsSectionNode() )
325  {
326  const SwSection& rSect = pNewNd->GetSectionNode()->GetSection();
327  if( rSect.IsHiddenFlag() || rSect.IsProtectFlag() )
328  m_aNdIdx = *pNewNd->EndOfSectionNode();
329  }
330  } while( !pNewNd->IsTextNode() );
331 
332  if( !m_aFlags.bAFormatByInput )
333  ::SetProgressState( m_aNdIdx.GetIndex() + m_nEndNdIdx - m_aEndNdIdx.GetIndex(),
334  m_pDoc->GetDocShell() );
335 
336  m_pCurTextNd = static_cast<SwTextNode*>(pNewNd);
337  m_pCurTextFrame = GetFrame( *m_pCurTextNd );
338 }
339 
341 {
342  // Is there something bound to the paragraph in the paragraph
343  // like Frames, DrawObjects, ...
344  SwNodeIndex node(*rFrame.GetTextNodeFirst());
345  do
346  {
347  if (node.GetNode().GetAnchoredFlys() != nullptr)
348  {
349  assert(!node.GetNode().GetAnchoredFlys()->empty());
350  return true;
351  }
352  ++node;
353  }
354  while (sw::FrameContainsNode(rFrame, node.GetIndex()));
355  return false;
356 }
357 
358 const SwTextFrame* SwAutoFormat::GetNextNode(bool const isCheckEnd) const
359 {
360  SwNodeIndex tmp(m_aNdIdx);
361  sw::GotoNextLayoutTextFrame(tmp, m_pEditShell->GetLayout());
362  if ((isCheckEnd && m_aEndNdIdx <= tmp) || !tmp.GetNode().IsTextNode())
363  return nullptr;
364  // note: the returned frame is not necessarily formatted, have to call
365  // EnsureFormatted for that
366  return static_cast<SwTextFrame*>(tmp.GetNode().GetTextNode()->getLayoutFrame(m_pEditShell->GetLayout()));
367 }
368 
369 bool SwAutoFormat::IsOneLine(const SwTextFrame & rFrame) const
370 {
371  SwTextFrameInfo aFInfo( EnsureFormatted(rFrame) );
372  return aFInfo.IsOneLine();
373 }
374 
375 bool SwAutoFormat::IsFastFullLine(const SwTextFrame & rFrame) const
376 {
377  bool bRet = m_aFlags.bRightMargin;
378  if( bRet )
379  {
380  SwTextFrameInfo aFInfo( EnsureFormatted(rFrame) );
381  bRet = aFInfo.IsFilled( m_aFlags.nRightMargin );
382  }
383  return bRet;
384 }
385 
386 bool SwAutoFormat::IsEnumericChar(const SwTextFrame& rFrame) const
387 {
388  const OUString& rText = rFrame.GetText();
389  TextFrameIndex nBlanks(GetLeadingBlanks(rText));
390  const TextFrameIndex nLen = TextFrameIndex(rText.getLength()) - nBlanks;
391  if( !nLen )
392  return false;
393 
394  // -, +, * separated by blank ??
395  if (TextFrameIndex(2) < nLen && IsSpace(rText[sal_Int32(nBlanks) + 1]))
396  {
397  if (StrChr(pBulletChar, rText[sal_Int32(nBlanks)]))
398  return true;
399  // Should there be a symbol font at the position?
400  SwTextFrameInfo aFInfo( EnsureFormatted(rFrame) );
401  if (aFInfo.IsBullet(nBlanks))
402  return true;
403  }
404 
405  // 1.) / 1. / 1.1.1 / (1). / (1) / ...
406  return USHRT_MAX != GetDigitLevel(rFrame, nBlanks);
407 }
408 
410 {
411  // Search more than 5 consecutive blanks/tabs in the string.
412  OUString sTmp( DelLeadingBlanks(rFrame.GetText()) );
413  const sal_Int32 nLen = sTmp.getLength();
414  sal_Int32 nIdx = 0;
415  while (nIdx < nLen)
416  {
417  // Skip non-blanks
418  while (nIdx < nLen && !IsSpace(sTmp[nIdx])) ++nIdx;
419  if (nIdx == nLen)
420  return false;
421  // Then count consecutive blanks
422  const sal_Int32 nFirst = nIdx;
423  while (nIdx < nLen && IsSpace(sTmp[nIdx])) ++nIdx;
424  // And exit if enough consecutive blanks were found
425  if (nIdx-nFirst > 5)
426  return true;
427  }
428  return false;
429 }
430 
431 sal_uInt16 SwAutoFormat::CalcLevel(const SwTextFrame & rFrame,
432  sal_uInt16 *const pDigitLvl) const
433 {
434  sal_uInt16 nLvl = 0, nBlnk = 0;
435  const OUString& rText = rFrame.GetText();
436  if( pDigitLvl )
437  *pDigitLvl = USHRT_MAX;
438 
440  {
441  if( m_aFlags.bAFormatByInput )
442  {
443  // this is very non-obvious: on the *first* invocation of
444  // AutoFormat, the node will have the tabs (any number) converted
445  // to a fixed indent in BuildTextIndent(), and the number of tabs
446  // is stored in the node;
447  // on the *second* invocation of AutoFormat, CalcLevel() will
448  // retrieve the stored number, and it will be used by
449  // BuildHeadLine() to select the corresponding heading style.
450  nLvl = rFrame.GetTextNodeForParaProps()->GetAutoFormatLvl();
451  const_cast<SwTextNode *>(rFrame.GetTextNodeForParaProps())->SetAutoFormatLvl(0);
452  if( nLvl )
453  return nLvl;
454  }
455  ++nLvl;
456  }
457 
458  for (TextFrameIndex n(0),
459  nEnd(rText.getLength()); n < nEnd; ++n)
460  {
461  switch (rText[sal_Int32(n)])
462  {
463  case ' ': if( 3 == ++nBlnk )
464  {
465  ++nLvl;
466  nBlnk = 0;
467  }
468  break;
469  case '\t': ++nLvl;
470  nBlnk = 0;
471  break;
472  default:
473  if( pDigitLvl )
474  // test 1.) / 1. / 1.1.1 / (1). / (1) / ...
475  *pDigitLvl = GetDigitLevel(rFrame, n);
476  return nLvl;
477  }
478  }
479  return nLvl;
480 }
481 
482 sal_Int32 SwAutoFormat::GetBigIndent(TextFrameIndex & rCurrentSpacePos) const
483 {
484  SwTextFrameInfo aFInfo( m_pCurTextFrame );
485  const SwTextFrame* pNextFrame = nullptr;
486 
487  if( !m_bMoreLines )
488  {
489  pNextFrame = GetNextNode();
490  if (!CanJoin(pNextFrame) || !IsOneLine(*pNextFrame))
491  return 0;
492 
493  pNextFrame = EnsureFormatted(*pNextFrame);
494  }
495 
496  return aFInfo.GetBigIndent( rCurrentSpacePos, pNextFrame );
497 }
498 
499 bool SwAutoFormat::IsNoAlphaLine(const SwTextFrame & rFrame) const
500 {
501  const OUString& rStr = rFrame.GetText();
502  if( rStr.isEmpty() )
503  return false;
504  // or better: determine via number of AlphaNum and !AlphaNum characters
505  sal_Int32 nANChar = 0, nBlnk = 0;
506 
507  for (TextFrameIndex n(0),
508  nEnd(rStr.getLength()); n < nEnd; ++n)
509  if (IsSpace(rStr[sal_Int32(n)]))
510  ++nBlnk;
511  else
512  {
513  auto const pair = rFrame.MapViewToModel(n);
514  CharClass& rCC = GetCharClass(pair.first->GetSwAttrSet().GetLanguage().GetLanguage());
515  if (rCC.isLetterNumeric(rStr, sal_Int32(n)))
516  ++nANChar;
517  }
518 
519  // If there are 75% of non-alphanumeric characters, then true
520  sal_uLong nLen = rStr.getLength() - nBlnk;
521  nLen = ( nLen * 3 ) / 4; // long overflow, if the strlen > sal_uInt16
522  return sal_Int32(nLen) < (rStr.getLength() - nANChar - nBlnk);
523 }
524 
526 {
527  if( !m_aFlags.bSetBorder )
528  return false;
529 
530  OUString const& rText(m_pCurTextFrame->GetText());
531  int eState = 0;
532  sal_Int32 nCnt = 0;
533  while (nCnt < rText.getLength())
534  {
535  int eTmp = 0;
536  switch (rText[nCnt])
537  {
538  case '-': eTmp = 1; break;
539  case '_': eTmp = 2; break;
540  case '=': eTmp = 3; break;
541  case '*': eTmp = 4; break;
542  case '~': eTmp = 5; break;
543  case '#': eTmp = 6; break;
544  default:
545  return false;
546  }
547  if( 0 == eState )
548  eState = eTmp;
549  else if( eState != eTmp )
550  return false;
551  ++nCnt;
552  }
553 
554  if( 2 < nCnt )
555  {
556  // then underline the previous paragraph if one exists
557  DelEmptyLine( false ); // -> point will be on end of current paragraph
558  // WARNING: rText may be deleted now, m_pCurTextFrame may be nullptr
559  m_aDelPam.SetMark();
560  // apply to last node & rely on InsertItemSet to apply it to props-node
561  m_aDelPam.GetMark()->nContent = 0;
562 
564  switch( eState )
565  {
566  case 1: // single, 0.05 pt
567  aLine.SetBorderLineStyle(SvxBorderLineStyle::SOLID);
568  aLine.SetWidth( DEF_LINE_WIDTH_0 );
569  break;
570  case 2: // single, 1.0 pt
571  aLine.SetBorderLineStyle(SvxBorderLineStyle::SOLID);
572  aLine.SetWidth( DEF_LINE_WIDTH_1 );
573  break;
574  case 3: // double, 1.0 pt
575  aLine.SetBorderLineStyle(SvxBorderLineStyle::DOUBLE);
576  aLine.SetWidth( DEF_LINE_WIDTH_1 );
577  break;
578  case 4: // double (thick/thin), 4.0 pt
579  aLine.SetBorderLineStyle(SvxBorderLineStyle::THICKTHIN_SMALLGAP);
580  aLine.SetWidth( DEF_LINE_WIDTH_3 );
581  break;
582  case 5: // double (thin/thick), 4.0 pt
583  aLine.SetBorderLineStyle(SvxBorderLineStyle::THINTHICK_SMALLGAP);
584  aLine.SetWidth( DEF_LINE_WIDTH_3 );
585  break;
586  case 6: // double, 2.5 pt
587  aLine.SetBorderLineStyle(SvxBorderLineStyle::DOUBLE);
588  aLine.SetWidth( DEF_LINE_WIDTH_2 );
589  break;
590  }
591  SfxItemSet aSet(m_pDoc->GetAttrPool(),
593  RES_BOX, RES_BOX>{});
594  aSet.Put( SwParaConnectBorderItem( false ) );
595  SvxBoxItem aBox( RES_BOX );
596  aBox.SetLine( &aLine, SvxBoxItemLine::BOTTOM );
597  aBox.SetDistance(42, SvxBoxItemLine::BOTTOM ); // ~0,75 mm
598  aSet.Put(aBox);
599  m_pDoc->getIDocumentContentOperations().InsertItemSet(m_aDelPam, aSet,
600  SetAttrMode::DEFAULT, m_pEditShell->GetLayout());
601 
602  m_aDelPam.DeleteMark();
603  }
604  return 2 < nCnt;
605 }
606 
608 {
609  if( !m_aFlags.bCreateTable || !m_aFlags.bAFormatByInput ||
610  m_pCurTextNd->FindTableNode() )
611  return false;
612 
613  const OUString& rTmp = m_pCurTextFrame->GetText();
614  TextFrameIndex nSttPlus(GetLeadingBlanks(rTmp));
615  TextFrameIndex nEndPlus(GetTrailingBlanks(rTmp));
616  sal_Unicode cChar;
617 
618  if (TextFrameIndex(2) > nEndPlus - nSttPlus
619  || ('+' != (cChar = rTmp[sal_Int32(nSttPlus)]) && '|' != cChar)
620  || ('+' != (cChar = rTmp[sal_Int32(nEndPlus) - 1]) && '|' != cChar))
621  return false;
622 
623  SwTextFrameInfo aInfo( m_pCurTextFrame );
624 
625  TextFrameIndex n = nSttPlus;
626  std::vector<sal_uInt16> aPosArr;
627 
628  while (n < TextFrameIndex(rTmp.getLength()))
629  {
630  switch (rTmp[sal_Int32(n)])
631  {
632  case '-':
633  case '_':
634  case '=':
635  case ' ':
636  case '\t':
637  break;
638 
639  case '+':
640  case '|':
641  aPosArr.push_back( static_cast<sal_uInt16>(aInfo.GetCharPos(n)) );
642  break;
643 
644  default:
645  return false;
646  }
647  if( ++n == nEndPlus )
648  break;
649  }
650 
651  if( 1 < aPosArr.size() )
652  {
653  // get the text node's alignment
654  sal_uInt16 nColCnt = aPosArr.size() - 1;
655  SwTwips nSttPos = aPosArr[ 0 ];
656  sal_Int16 eHori;
657  switch (m_pCurTextFrame->GetTextNodeForParaProps()->GetSwAttrSet().GetAdjust().GetAdjust())
658  {
659  case SvxAdjust::Center: eHori = text::HoriOrientation::CENTER; break;
660  case SvxAdjust::Right: eHori = text::HoriOrientation::RIGHT; break;
661 
662  default:
663  if( nSttPos )
664  {
666  // then - as last - we need to add the current frame width into the array
667  aPosArr.push_back( static_cast<sal_uInt16>(m_pCurTextFrame->getFrameArea().Width()) );
668  }
669  else
670  eHori = text::HoriOrientation::LEFT;
671  break;
672  }
673 
674  // then create a table that matches the character
675  DelEmptyLine();
676  // WARNING: rTmp may be deleted now, m_pCurTextFrame may be nullptr
677  SwNodeIndex aIdx( m_aDelPam.GetPoint()->nNode );
678  m_aDelPam.Move( fnMoveForward );
680  *m_aDelPam.GetPoint(), 1, nColCnt, eHori,
681  nullptr, &aPosArr );
682  m_aDelPam.GetPoint()->nNode = aIdx;
683  }
684  return 1 < aPosArr.size();
685 }
686 
687 OUString SwAutoFormat::DelLeadingBlanks( const OUString& rStr )
688 {
689  sal_Int32 nL, n;
690  for( nL = rStr.getLength(), n = 0; n < nL && IsSpace( rStr[n] ); ++n )
691  ;
692  if( n ) // no Spaces
693  return rStr.copy(n);
694  return rStr;
695 }
696 
697 OUString SwAutoFormat::DelTrailingBlanks( const OUString& rStr )
698 {
699  sal_Int32 nL = rStr.getLength(), n = nL;
700  if( !nL )
701  return rStr;
702 
703  while( --n && IsSpace( rStr[ n ] ) )
704  ;
705  if( n+1 != nL ) // no Spaces
706  return rStr.copy( 0, n+1 );
707  return rStr;
708 }
709 
710 sal_Int32 SwAutoFormat::GetLeadingBlanks( const OUString& rStr )
711 {
712  sal_Int32 nL;
713  sal_Int32 n;
714 
715  for( nL = rStr.getLength(), n = 0; n < nL && IsSpace( rStr[ n ] ); ++n )
716  ;
717  return n;
718 }
719 
720 sal_Int32 SwAutoFormat::GetTrailingBlanks( const OUString& rStr )
721 {
722  sal_Int32 nL = rStr.getLength(), n = nL;
723  if( !nL )
724  return 0;
725 
726  while( --n && IsSpace( rStr[ n ] ) )
727  ;
728  return ++n;
729 }
730 
732 {
733  const OUString& rText = rFrame.GetText();
734  for (TextFrameIndex n(0),
735  nEnd(rText.getLength()); n < nEnd; ++n)
736  if (!IsSpace(rText[sal_Int32(n)]))
737  {
738  auto const pair = rFrame.MapViewToModel(n);
739  CharClass& rCC = GetCharClass( pair.first->GetSwAttrSet().
740  GetLanguage().GetLanguage() );
741  sal_Int32 nCharType = rCC.getCharacterType(rText, sal_Int32(n));
742  return CharClass::isLetterType( nCharType ) &&
743  0 != ( i18n::KCharacterType::UPPER &
744  nCharType );
745  }
746  return false;
747 }
748 
749 sal_uInt16
751  OUString* pPrefix, OUString* pPostfix, OUString* pNumTypes ) const
752 {
753 
754  // check for 1.) / 1. / 1.1.1 / (1). / (1) / ...
755  const OUString& rText = rFrame.GetText();
756  sal_Int32 nPos(rPos);
757  int eScan = NONE;
758 
759  sal_uInt16 nStart = 0;
760  sal_uInt8 nDigitLvl = 0, nDigitCnt = 0;
761  // count number of parenthesis to assure a sensible order is found
762  sal_uInt16 nOpeningParentheses = 0;
763  sal_uInt16 nClosingParentheses = 0;
764 
765  while (nPos < rText.getLength() && nDigitLvl < MAXLEVEL - 1)
766  {
767  auto const pair = rFrame.MapViewToModel(TextFrameIndex(nPos));
768  CharClass& rCC = GetCharClass(pair.first->GetSwAttrSet().GetLanguage().GetLanguage());
769  const sal_Unicode cCurrentChar = rText[nPos];
770  if( ('0' <= cCurrentChar && '9' >= cCurrentChar) ||
771  (0xff10 <= cCurrentChar && 0xff19 >= cCurrentChar) )
772  {
773  if( eScan & DELIM )
774  {
775  if( eScan & CHG ) // not if it starts with a number
776  {
777  ++nDigitLvl;
778  if( pPostfix )
779  *pPostfix += "\x01";
780  }
781 
782  if( pNumTypes )
783  *pNumTypes += OUStringChar(sal_Unicode('0' + SVX_NUM_ARABIC));
784 
785  eScan = eScan | CHG;
786  }
787  else if( pNumTypes && !(eScan & DIGIT) )
788  *pNumTypes += OUStringChar(sal_Unicode('0' + SVX_NUM_ARABIC));
789 
790  eScan &= ~DELIM; // remove Delim
791  if( 0 != (eScan & ~CHG) && DIGIT != (eScan & ~CHG))
792  return USHRT_MAX;
793 
794  eScan |= DIGIT; // add Digit
795  if( 3 == ++nDigitCnt ) // more than 2 numbers are not an enum anymore
796  return USHRT_MAX;
797 
798  nStart *= 10;
799  nStart += cCurrentChar <= '9' ? cCurrentChar - '0' : cCurrentChar - 0xff10;
800  }
801  else if( rCC.isAlpha( rText, nPos ) )
802  {
803  bool bIsUpper =
804  0 != ( i18n::KCharacterType::UPPER &
805  rCC.getCharacterType( rText, nPos ));
806  sal_Unicode cLow = rCC.lowercase(rText, nPos, 1)[0], cNumTyp;
807  int eTmpScan;
808 
809  // Roman numbers are "mdclxvi". Since we want to start numbering with c or d more often,
810  // convert first to characters and later to roman numbers if needed.
811  if( 256 > cLow && strchr( "mdclxvi", cLow ) )
812  {
813  if( bIsUpper )
814  {
815  cNumTyp = '0' + SVX_NUM_ROMAN_UPPER;
816  eTmpScan = UPPER_ROMAN;
817  }
818  else
819  {
820  cNumTyp = '0' + SVX_NUM_ROMAN_LOWER;
821  eTmpScan = LOWER_ROMAN;
822  }
823  }
824  else if( bIsUpper )
825  {
826  cNumTyp = '0' + SVX_NUM_CHARS_UPPER_LETTER;
827  eTmpScan = UPPER_ALPHA;
828  }
829  else
830  {
831  cNumTyp = '0' + SVX_NUM_CHARS_LOWER_LETTER;
832  eTmpScan = LOWER_ALPHA;
833  }
834 
835  // Switch to roman numbers (only for c/d!)
836  if( 1 == nDigitCnt && ( eScan & (UPPER_ALPHA|LOWER_ALPHA) ) &&
837  ( 3 == nStart || 4 == nStart) && 256 > cLow &&
838  strchr( "mdclxvi", cLow ) &&
839  (( eScan & UPPER_ALPHA ) ? (eTmpScan & (UPPER_ALPHA|UPPER_ROMAN))
840  : (eTmpScan & (LOWER_ALPHA|LOWER_ROMAN))) )
841  {
842  sal_Unicode c = '0';
843  nStart = 3 == nStart ? 100 : 500;
844  if( UPPER_ALPHA == eTmpScan )
845  {
846  eTmpScan = UPPER_ROMAN;
847  c += SVX_NUM_ROMAN_UPPER;
848  }
849  else
850  {
851  eTmpScan = LOWER_ROMAN;
852  c += SVX_NUM_ROMAN_LOWER;
853  }
854 
855  eScan = (eScan & ~(UPPER_ALPHA|LOWER_ALPHA)) | eTmpScan;
856  if( pNumTypes )
857  (*pNumTypes) = pNumTypes->replaceAt( pNumTypes->getLength() - 1, 1, OUString(c) );
858  }
859 
860  if( eScan & DELIM )
861  {
862  if( eScan & CHG ) // not if it starts with a number
863  {
864  ++nDigitLvl;
865  if( pPostfix )
866  *pPostfix += "\x01";
867  }
868 
869  if( pNumTypes )
870  *pNumTypes += OUStringChar(cNumTyp);
871  eScan = eScan | CHG;
872  }
873  else if( pNumTypes && !(eScan & eTmpScan) )
874  *pNumTypes += OUStringChar(cNumTyp);
875 
876  eScan &= ~DELIM; // remove Delim
877 
878  // if another type is set, stop here
879  if( 0 != ( eScan & ~CHG ) && eTmpScan != ( eScan & ~CHG ))
880  return USHRT_MAX;
881 
882  if( eTmpScan & (UPPER_ALPHA | LOWER_ALPHA) )
883  {
884  // allow characters only if they appear once
885  return USHRT_MAX;
886  }
887  else
888  {
889  // roman numbers, check if valid characters
890  sal_uInt16 nVal;
891  bool bError = false;
892  switch( cLow )
893  {
894  case 'm': nVal = 1000; goto CHECK_ROMAN_1;
895  case 'd': nVal = 500; goto CHECK_ROMAN_5;
896  case 'c': nVal = 100; goto CHECK_ROMAN_1;
897  case 'l': nVal = 50; goto CHECK_ROMAN_5;
898  case 'x': nVal = 10; goto CHECK_ROMAN_1;
899  case 'v': nVal = 5; goto CHECK_ROMAN_5;
900 
901 CHECK_ROMAN_1:
902  {
903  int nMod5 = nStart % (nVal * 5);
904  int nLast = nStart % nVal;
905  int n10 = nVal / 10;
906 
907  if( nMod5 == ((3 * nVal) + n10 ) ||
908  nMod5 == ((4 * nVal) + n10 ) ||
909  nLast == n10 )
910  nStart = static_cast<sal_uInt16>(nStart + (n10 * 8));
911  else if( nMod5 == 0 ||
912  nMod5 == (1 * nVal) ||
913  nMod5 == (2 * nVal) )
914  nStart = nStart + nVal;
915  else
916  bError = true;
917  }
918  break;
919 
920 CHECK_ROMAN_5:
921  {
922  if( ( nStart / nVal ) & 1 )
923  bError = true;
924  else
925  {
926  int nMod = nStart % nVal;
927  int n10 = nVal / 5;
928  if( n10 == nMod )
929  nStart = static_cast<sal_uInt16>(nStart + (3 * n10));
930  else if( 0 == nMod )
931  nStart = nStart + nVal;
932  else
933  bError = true;
934  }
935  }
936  break;
937 
938  case 'i':
939  if( nStart % 5 >= 3 )
940  bError = true;
941  else
942  nStart += 1;
943  break;
944 
945  default:
946  bError = true;
947  }
948 
949  if( bError )
950  return USHRT_MAX;
951  }
952  eScan |= eTmpScan; // add Digit
953  ++nDigitCnt;
954  }
955  else if( (256 > cCurrentChar &&
956  strchr( ".)(", cCurrentChar )) ||
957  0x3002 == cCurrentChar /* Chinese trad. dot */||
958  0xff0e == cCurrentChar /* Japanese dot */||
959  0xFF08 == cCurrentChar /* opening bracket Chin./Jap.*/||
960  0xFF09 == cCurrentChar )/* closing bracket Chin./Jap. */
961  {
962  if(cCurrentChar == '(' || cCurrentChar == 0xFF09)
963  nOpeningParentheses++;
964  else if(cCurrentChar == ')'|| cCurrentChar == 0xFF08)
965  nClosingParentheses++;
966  // only if no numbers were read until here
967  if( pPrefix && !( eScan & ( NO_DELIM | CHG )) )
968  *pPrefix += OUStringChar(rText[nPos]);
969  else if( pPostfix )
970  *pPostfix += OUStringChar(rText[nPos]);
971 
972  if( NO_DELIM & eScan )
973  {
974  eScan |= CHG;
975  if( pPrefix )
976  *pPrefix += "\x01" + OUString::number( nStart );
977  }
978  eScan &= ~NO_DELIM; // remove Delim
979  eScan |= DELIM; // add Digit
980  nDigitCnt = 0;
981  nStart = 0;
982  }
983  else
984  break;
985  ++nPos;
986  }
987  if (!( CHG & eScan ) || rPos == TextFrameIndex(nPos) ||
988  nPos == rText.getLength() || !IsSpace(rText[nPos]) ||
989  (nOpeningParentheses > nClosingParentheses))
990  return USHRT_MAX;
991 
992  if( (NO_DELIM & eScan) && pPrefix ) // do not forget the last one
993  *pPrefix += "\x01" + OUString::number( nStart );
994 
995  rPos = TextFrameIndex(nPos);
996  return nDigitLvl; // 0 .. 9 (MAXLEVEL - 1)
997 }
998 
999 void SwAutoFormat::SetColl( sal_uInt16 nId, bool bHdLineOrText )
1000 {
1001  m_aDelPam.DeleteMark();
1002  m_aDelPam.GetPoint()->nNode = *m_pCurTextFrame->GetTextNodeForParaProps();
1003  m_aDelPam.GetPoint()->nContent.Assign(m_aDelPam.GetPoint()->nNode.GetNode().GetContentNode(), 0);
1004 
1005  // keep hard tabs, alignment, language, hyphenation, DropCaps and nearly all frame attributes
1006  SfxItemSet aSet(
1007  m_pDoc->GetAttrPool(),
1008  svl::Items<
1013 
1014  if (m_aDelPam.GetPoint()->nNode.GetNode().GetTextNode()->HasSwAttrSet())
1015  {
1016  aSet.Put(*m_aDelPam.GetPoint()->nNode.GetNode().GetTextNode()->GetpSwAttrSet());
1017  // take HeaderLine/TextBody only if centered or right aligned, otherwise only justification
1018  SvxAdjustItem const * pAdj;
1019  if( SfxItemState::SET == aSet.GetItemState( RES_PARATR_ADJUST,
1020  false, reinterpret_cast<const SfxPoolItem**>(&pAdj) ))
1021  {
1022  SvxAdjust eAdj = pAdj->GetAdjust();
1023  if( bHdLineOrText ? (SvxAdjust::Right != eAdj &&
1024  SvxAdjust::Center != eAdj)
1025  : SvxAdjust::Block != eAdj )
1026  aSet.ClearItem( RES_PARATR_ADJUST );
1027  }
1028  }
1029 
1030  m_pDoc->SetTextFormatCollByAutoFormat( *m_aDelPam.GetPoint(), nId, &aSet );
1031 }
1032 
1033 static bool HasSelBlanks(
1034  SwTextFrame const*const pStartFrame, TextFrameIndex & rStartIndex,
1035  SwTextFrame const*const pEndFrame, TextFrameIndex & rEndIndex)
1036 {
1037  if (TextFrameIndex(0) < rEndIndex
1038  && rEndIndex < TextFrameIndex(pEndFrame->GetText().getLength())
1039  && ' ' == pEndFrame->GetText()[sal_Int32(rEndIndex) - 1])
1040  {
1041  --rEndIndex;
1042  return true;
1043  }
1044  if (rStartIndex < TextFrameIndex(pStartFrame->GetText().getLength())
1045  && ' ' == pStartFrame->GetText()[sal_Int32(rStartIndex)])
1046  {
1047  ++rStartIndex;
1048  return true;
1049  }
1050  return false;
1051 }
1052 
1054 {
1055  const SfxItemSet *const pSet = rTextFrame.GetTextNodeFirst()->GetpSwAttrSet();
1056  if( !pSet )
1057  return false;
1058 
1059  const SfxPoolItem* pItem;
1060  if( SfxItemState::SET == pSet->GetItemState( RES_BREAK, false, &pItem )
1061  && SvxBreak::NONE != static_cast<const SvxFormatBreakItem*>(pItem)->GetBreak() )
1062  return true;
1063 
1064  if( SfxItemState::SET == pSet->GetItemState( RES_PAGEDESC, false, &pItem )
1065  && static_cast<const SwFormatPageDesc*>(pItem)->GetPageDesc()
1066  && UseOnPage::NONE != static_cast<const SwFormatPageDesc*>(pItem)->GetPageDesc()->GetUseOn() )
1067  return true;
1068  return false;
1069 }
1070 
1073 {
1074  const OUString& rStr = rTextFrame.GetText();
1075  sal_Int32 n = rStr.getLength();
1076  if( !n )
1077  return true;
1078 
1079  while( --n && IsSpace( rStr[ n ] ) )
1080  ;
1081  return '.' == rStr[ n ];
1082 }
1083 
1085 void SwAutoFormat::DeleteLeadingTrailingBlanks(bool bStart, bool bEnd)
1086 {
1087  if( !(m_aFlags.bAFormatByInput
1089  : m_aFlags.bAFormatDelSpacesAtSttEnd) )
1090  return;
1091 
1092  // delete blanks at the end of the current and at the beginning of the next one
1093  m_aDelPam.DeleteMark();
1094  TextFrameIndex nPos(GetLeadingBlanks(m_pCurTextFrame->GetText()));
1095  if (bStart && TextFrameIndex(0) != nPos)
1096  {
1097  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(TextFrameIndex(0));
1098  m_aDelPam.SetMark();
1099  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nPos);
1100  DeleteSel( m_aDelPam );
1101  m_aDelPam.DeleteMark();
1102  }
1103  nPos = TextFrameIndex(GetTrailingBlanks(m_pCurTextFrame->GetText()));
1104  if (bEnd && TextFrameIndex(m_pCurTextFrame->GetText().getLength()) != nPos)
1105  {
1106  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(
1107  TextFrameIndex(m_pCurTextFrame->GetText().getLength()));
1108  m_aDelPam.SetMark();
1109  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nPos);
1110  DeleteSel( m_aDelPam );
1111  m_aDelPam.DeleteMark();
1112  }
1113 }
1114 
1115 namespace sw {
1116 
1117 bool GetRanges(std::vector<std::shared_ptr<SwUnoCursor>> & rRanges,
1118  SwDoc & rDoc, SwPaM const& rDelPam)
1119 {
1120  bool isNoRedline(true);
1123  if (!(rIDRA.GetRedlineFlags() & RedlineFlags::ShowDelete))
1124  {
1125  return isNoRedline;
1126  }
1127  rIDRA.GetRedline(*rDelPam.Start(), &tmp);
1128  SwPosition const* pCurrent(rDelPam.Start());
1129  for ( ; tmp < rIDRA.GetRedlineTable().size(); ++tmp)
1130  {
1131  SwRangeRedline const*const pRedline(rIDRA.GetRedlineTable()[tmp]);
1132  if (*rDelPam.End() <= *pRedline->Start())
1133  {
1134  break;
1135  }
1136  if (*pRedline->End() <= *rDelPam.Start())
1137  {
1138  continue;
1139  }
1140  if (pRedline->GetType() == RedlineType::Delete)
1141  {
1142  assert(*pRedline->Start() != *pRedline->End());
1143  isNoRedline = false;
1144  if (*pCurrent < *pRedline->Start())
1145  {
1146  rRanges.push_back(rDoc.CreateUnoCursor(*pCurrent));
1147  rRanges.back()->SetMark();
1148  *rRanges.back()->GetPoint() = *pRedline->Start();
1149  }
1150  pCurrent = pRedline->End();
1151  }
1152  }
1153  if (!isNoRedline && *pCurrent < *rDelPam.End())
1154  {
1155  rRanges.push_back(rDoc.CreateUnoCursor(*pCurrent));
1156  rRanges.back()->SetMark();
1157  *rRanges.back()->GetPoint() = *rDelPam.End();
1158  }
1159  return isNoRedline;
1160 }
1161 
1162 } // namespace sw
1163 
1165 {
1166  std::vector<std::shared_ptr<SwUnoCursor>> ranges; // need correcting cursor
1167  if (GetRanges(ranges, *m_pDoc, rDelPam))
1168  {
1169  DeleteSelImpl(rDelPam, rDelPam);
1170  }
1171  else
1172  {
1173  for (auto const& pCursor : ranges)
1174  {
1175  DeleteSelImpl(*pCursor, rDelPam);
1176  }
1177  }
1178 }
1179 
1180 void SwAutoFormat::DeleteSelImpl(SwPaM & rDelPam, SwPaM & rPamToCorrect)
1181 {
1182  if (m_aFlags.bWithRedlining || &rDelPam != &rPamToCorrect)
1183  {
1184  // Add to Shell-Cursor-Ring so that DelPam will be moved as well!
1185  SwPaM* pShCursor = m_pEditShell->GetCursor_();
1186  SwPaM aTmp( *m_pCurTextNd, 0, pShCursor );
1187 
1188  SwPaM* pPrev = rPamToCorrect.GetPrev();
1189  rPamToCorrect.GetRingContainer().merge( pShCursor->GetRingContainer() );
1190 
1191  m_pEditShell->DeleteSel( rDelPam );
1192 
1193  // and remove Pam again:
1194  SwPaM* p;
1195  SwPaM* pNext = &rPamToCorrect;
1196  do {
1197  p = pNext;
1198  pNext = p->GetNext();
1199  p->MoveTo( &rPamToCorrect );
1200  } while( p != pPrev );
1201 
1202  m_aNdIdx = aTmp.GetPoint()->nNode;
1203  m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
1204  m_pCurTextFrame = GetFrame(*m_pCurTextNd); // keep it up to date
1205  }
1206  else
1207  m_pEditShell->DeleteSel( rDelPam );
1208 }
1209 
1211  bool const bIgnoreLeadingBlanks)
1212 {
1213  // delete blanks at the end of the current and at the beginning of the next one
1214  m_aDelPam.DeleteMark();
1215  TextFrameIndex nTrailingPos(GetTrailingBlanks(m_pCurTextFrame->GetText()));
1216 
1217  SwTextFrame const*const pEndFrame(pNextFrame ? pNextFrame : m_pCurTextFrame);
1218  TextFrameIndex nLeadingPos(0);
1219  if (pNextFrame)
1220  {
1221  nLeadingPos = TextFrameIndex(
1222  bIgnoreLeadingBlanks ? 0 : GetLeadingBlanks(pNextFrame->GetText()));
1223  }
1224  else
1225  {
1226  nLeadingPos = TextFrameIndex(m_pCurTextFrame->GetText().getLength());
1227  }
1228 
1229  // Is there a Blank at the beginning or end?
1230  // Do not delete it, it will be inserted again.
1231  bool bHasBlnks = HasSelBlanks(m_pCurTextFrame, nTrailingPos, pEndFrame, nLeadingPos);
1232 
1233  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nTrailingPos);
1234  m_aDelPam.SetMark();
1235  *m_aDelPam.GetPoint() = pEndFrame->MapViewToModelPos(nLeadingPos);
1236 
1237  if( *m_aDelPam.GetPoint() != *m_aDelPam.GetMark() )
1238  DeleteSel( m_aDelPam );
1239  m_aDelPam.DeleteMark();
1240  // note: keep m_aDelPam point at insert pos. for clients
1241 
1242  return !bHasBlnks;
1243 }
1244 
1245 void SwAutoFormat::DelEmptyLine( bool bTstNextPara )
1246 {
1248  // delete blanks in empty paragraph
1249  m_aDelPam.DeleteMark();
1250  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(
1251  TextFrameIndex(0));
1252  m_aDelPam.SetMark();
1253 
1254  m_aDelPam.GetMark()->nNode = m_pCurTextFrame->GetTextNodeFirst()->GetIndex() - 1;
1255  SwTextNode* pTNd = m_aDelPam.GetNode( false ).GetTextNode();
1256  if( pTNd )
1257  // first use the previous text node
1258  m_aDelPam.GetMark()->nContent.Assign(pTNd, pTNd->GetText().getLength());
1259  else if( bTstNextPara )
1260  {
1261  // then try the next (at the beginning of a Doc, table cells, frames, ...)
1262  m_aDelPam.GetMark()->nNode = (m_pCurTextFrame->GetMergedPara()
1263  ? m_pCurTextFrame->GetMergedPara()->pLastNode
1264  : m_pCurTextNd
1265  )->GetIndex() + 1;
1266  pTNd = m_aDelPam.GetNode( false ).GetTextNode();
1267  if( pTNd )
1268  {
1269  m_aDelPam.GetMark()->nContent.Assign( pTNd, 0 );
1270  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(
1271  TextFrameIndex(m_pCurTextFrame->GetText().getLength()));
1272  }
1273  }
1274  if( pTNd )
1275  { // join with previous or next paragraph
1276  DeleteSel(m_aDelPam);
1277  }
1278  assert(m_aDelPam.GetNode().IsTextNode());
1279  assert(!m_aDelPam.HasMark());
1280  m_aDelPam.SetMark(); // mark remains at join position
1281  m_pCurTextFrame = GetFrame(*m_aDelPam.GetNode().GetTextNode());
1282  // replace until the end of the merged paragraph
1283  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(
1284  TextFrameIndex(m_pCurTextFrame->GetText().getLength()));
1285  if (*m_aDelPam.GetPoint() != *m_aDelPam.GetMark())
1286  { // tdf#137245 replace (not delete) to preserve any flys
1287  m_pDoc->getIDocumentContentOperations().ReplaceRange(m_aDelPam, "", false);
1288  }
1289 
1290  m_aDelPam.DeleteMark();
1291  ClearRedlineText();
1292  // note: this likely has deleted m_pCurTextFrame - update it...
1293  m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
1294  m_pCurTextFrame = m_pCurTextNd ? GetFrame( *m_pCurTextNd ) : nullptr;
1295 }
1296 
1297 void SwAutoFormat::DelMoreLinesBlanks( bool bWithLineBreaks )
1298 {
1299  if( !(m_aFlags.bAFormatByInput
1301  : m_aFlags.bAFormatDelSpacesBetweenLines) )
1302  return;
1303 
1304  // delete all blanks on the left and right of the indentation
1305  m_aDelPam.DeleteMark();
1306 
1307  SwTextFrameInfo aFInfo( m_pCurTextFrame );
1308  std::vector<std::pair<TextFrameIndex, TextFrameIndex>> spaces;
1309  aFInfo.GetSpaces(spaces, !m_aFlags.bAFormatByInput || bWithLineBreaks);
1310 
1311  // tdf#123285 iterate backwards - delete invalidates following indexes
1312  for (auto iter = spaces.rbegin(); iter != spaces.rend(); ++iter)
1313  {
1314  auto & rSpaceRange(*iter);
1315  assert(rSpaceRange.first != rSpaceRange.second);
1316  bool const bHasBlanks = HasSelBlanks(
1317  m_pCurTextFrame, rSpaceRange.first,
1318  m_pCurTextFrame, rSpaceRange.second);
1319  if (rSpaceRange.first != rSpaceRange.second)
1320  {
1321  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(rSpaceRange.first);
1322  m_aDelPam.SetMark();
1323  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(rSpaceRange.second);
1324  DeleteSel(m_aDelPam);
1325  if (!bHasBlanks)
1326  {
1327  m_pDoc->getIDocumentContentOperations().InsertString(m_aDelPam, OUString(' '));
1328  }
1329  m_aDelPam.DeleteMark();
1330  }
1331  }
1332 }
1333 
1335 {
1336  m_aDelPam.DeleteMark();
1337  m_aDelPam.GetPoint()->nNode = *m_pCurTextFrame->GetTextNodeFirst();
1338  m_aDelPam.GetPoint()->nContent.Assign(m_pCurTextFrame->GetTextNodeFirst(), 0);
1339  m_aDelPam.SetMark();
1340 
1341  --m_aDelPam.GetPoint()->nNode;
1342  SwTextNode* pTNd = m_aDelPam.GetNode().GetTextNode();
1343  if( pTNd )
1344  {
1345  // use the previous text node first
1346  m_aDelPam.GetPoint()->nContent.Assign(pTNd, pTNd->GetText().getLength());
1347  DeleteSel( m_aDelPam );
1348  }
1349  m_aDelPam.DeleteMark();
1350 }
1351 
1353 {
1355 
1356  // read all succeeding paragraphs that belong to this indentation
1357  bool bBreak = true;
1358  if( m_bMoreLines )
1359  DelMoreLinesBlanks( true );
1360  else
1361  bBreak = !IsFastFullLine(*m_pCurTextFrame)
1362  || IsBlanksInString(*m_pCurTextFrame)
1363  || IsSentenceAtEnd(*m_pCurTextFrame);
1365  if( !bBreak )
1366  {
1368  const SwTextFrame * pNextFrame = GetNextNode();
1369  if (pNextFrame && !m_bEnd)
1370  {
1371  do {
1372  bBreak = !IsFastFullLine(*pNextFrame)
1373  || IsBlanksInString(*pNextFrame)
1374  || IsSentenceAtEnd(*pNextFrame);
1375  if (DeleteJoinCurNextPara(pNextFrame))
1376  {
1377  m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, OUString(' ') );
1378  }
1379  if( bBreak )
1380  break;
1381  pNextFrame = GetNextNode();
1382  }
1383  while (CanJoin(pNextFrame)
1384  && !CalcLevel(*pNextFrame));
1385  }
1386  }
1388  AutoCorrect();
1389 }
1390 
1392 {
1394  // read all succeeding paragraphs that belong to this indentation
1395  bool bBreak = true;
1396  if( m_bMoreLines )
1397  DelMoreLinesBlanks( true );
1398  else
1399  bBreak = !IsFastFullLine(*m_pCurTextFrame)
1400  || IsBlanksInString(*m_pCurTextFrame)
1401  || IsSentenceAtEnd(*m_pCurTextFrame);
1402 
1403  if( m_aFlags.bAFormatByInput )
1404  {
1405  const_cast<SwTextNode*>(m_pCurTextFrame->GetTextNodeForParaProps())->SetAutoFormatLvl(
1406  static_cast<sal_uInt8>(CalcLevel(*m_pCurTextFrame)));
1407  }
1408 
1410  if( !bBreak )
1411  {
1413  const SwTextFrame * pNextFrame = GetNextNode();
1414  while (CanJoin(pNextFrame) &&
1415  CalcLevel(*pNextFrame))
1416  {
1417  bBreak = !IsFastFullLine(*pNextFrame)
1418  || IsBlanksInString(*pNextFrame)
1419  || IsSentenceAtEnd(*pNextFrame);
1420  if (DeleteJoinCurNextPara(pNextFrame))
1421  {
1422  m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, OUString(' ') );
1423  }
1424  if( bBreak )
1425  break;
1426  pNextFrame = GetNextNode();
1427  }
1428  }
1430  AutoCorrect();
1431 }
1432 
1434 {
1436  // read all succeeding paragraphs that belong to this text without indentation
1437  bool bBreak = true;
1438  if( m_bMoreLines )
1440  else
1441  bBreak = !IsFastFullLine(*m_pCurTextFrame)
1442  || IsBlanksInString(*m_pCurTextFrame)
1443  || IsSentenceAtEnd(*m_pCurTextFrame);
1444  SetColl( RES_POOLCOLL_TEXT, true );
1445  if( !bBreak )
1446  {
1448  const SwTextFrame * pNextFrame = GetNextNode();
1449  while (CanJoin(pNextFrame) &&
1450  !CalcLevel(*pNextFrame))
1451  {
1452  bBreak = !IsFastFullLine(*pNextFrame)
1453  || IsBlanksInString(*pNextFrame)
1454  || IsSentenceAtEnd(*pNextFrame);
1455  if (DeleteJoinCurNextPara(pNextFrame))
1456  {
1457  m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, OUString(' ') );
1458  }
1459  if( bBreak )
1460  break;
1461  const SwTextFrame *const pCurrNode = pNextFrame;
1462  pNextFrame = GetNextNode();
1463  if (!pNextFrame || pCurrNode == pNextFrame)
1464  break;
1465  }
1466  }
1468  AutoCorrect();
1469 }
1470 
1471 void SwAutoFormat::BuildEnum( sal_uInt16 nLvl, sal_uInt16 nDigitLevel )
1472 {
1474 
1475  bool bBreak = true;
1476 
1477  // first, determine current indentation and frame width
1478  SwTwips nFrameWidth = m_pCurTextFrame->getFramePrintArea().Width();
1479  SwTwips nLeftTextPos;
1480  {
1481  TextFrameIndex nPos(0);
1482  while (nPos < TextFrameIndex(m_pCurTextFrame->GetText().getLength())
1483  && IsSpace(m_pCurTextFrame->GetText()[sal_Int32(nPos)]))
1484  {
1485  ++nPos;
1486  }
1487 
1488  SwTextFrameInfo aInfo( m_pCurTextFrame );
1489  nLeftTextPos = aInfo.GetCharPos(nPos);
1490  nLeftTextPos -= m_pCurTextFrame->GetTextNodeForParaProps()->GetSwAttrSet().GetLRSpace().GetLeft();
1491  }
1492 
1493  if( m_bMoreLines )
1495  else
1496  bBreak = !IsFastFullLine(*m_pCurTextFrame)
1497  || IsBlanksInString(*m_pCurTextFrame)
1498  || IsSentenceAtEnd(*m_pCurTextFrame);
1499  bool bRTL = m_pEditShell->IsInRightToLeftText();
1501 
1502  bool bChgBullet = false, bChgEnum = false;
1503  TextFrameIndex nAutoCorrPos(0);
1504 
1505  // if numbering is set, get the current one
1506  SwNumRule aRule( m_pDoc->GetUniqueNumRuleName(),
1507  // #i89178#
1509 
1510  const SwNumRule* pCur = nullptr;
1511  if (m_aFlags.bSetNumRule)
1512  {
1513  pCur = m_pCurTextFrame->GetTextNodeForParaProps()->GetNumRule();
1514  if (pCur)
1515  {
1516  aRule = *pCur;
1517  }
1518  }
1519 
1520  // replace bullet character with defined one
1521  const OUString& rStr = m_pCurTextFrame->GetText();
1522  TextFrameIndex nTextStt(0);
1523  const sal_Unicode* pFndBulletChr = nullptr;
1524  if (m_aFlags.bChgEnumNum && 2 < rStr.getLength())
1525  pFndBulletChr = StrChr(pBulletChar, rStr[sal_Int32(nTextStt)]);
1526  if (nullptr != pFndBulletChr && IsSpace(rStr[sal_Int32(nTextStt) + 1]))
1527  {
1528  if( m_aFlags.bAFormatByInput )
1529  {
1530  if( m_aFlags.bSetNumRule )
1531  {
1534  bChgBullet = true;
1535  // Was the format already somewhere adjusted?
1536  if( !aRule.GetNumFormat( nLvl ) )
1537  {
1538  int nBulletPos = pFndBulletChr - pBulletChar;
1539  sal_UCS4 cBullChar;
1540  const vcl::Font* pBullFnt( nullptr );
1541  if( nBulletPos < cnPosEnDash )
1542  {
1543  cBullChar = m_aFlags.cBullet;
1544  pBullFnt = &m_aFlags.aBulletFont;
1545  }
1546  else
1547  {
1548  cBullChar = nBulletPos < cnPosEmDash
1551  // #i63395#
1552  // Only apply user defined default bullet font
1554  {
1555  pBullFnt = &numfunc::GetDefBulletFont();
1556  }
1557  }
1558 
1559  sal_Int32 nAbsPos = lBulletIndent;
1560  SwTwips nSpaceSteps = nLvl
1561  ? nLeftTextPos / nLvl
1562  : lBulletIndent;
1563  for( sal_uInt8 n = 0; n < MAXLEVEL; ++n, nAbsPos = nAbsPos + nSpaceSteps )
1564  {
1565  SwNumFormat aFormat( aRule.Get( n ) );
1566  aFormat.SetBulletFont( pBullFnt );
1567  aFormat.SetBulletChar( cBullChar );
1568  aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1569  // #i93908# clear suffix for bullet lists
1570  aFormat.SetPrefix(OUString());
1571  aFormat.SetSuffix(OUString());
1572  aFormat.SetFirstLineOffset( lBulletFirstLineOffset );
1573  aFormat.SetAbsLSpace( nAbsPos );
1574  if( !aFormat.GetCharFormat() )
1575  aFormat.SetCharFormat( pCFormat );
1576  if( bRTL )
1577  aFormat.SetNumAdjust( SvxAdjust::Right );
1578 
1579  aRule.Set( n, aFormat );
1580 
1581  if( n == nLvl &&
1582  nFrameWidth < ( nSpaceSteps * MAXLEVEL ) )
1583  nSpaceSteps = ( nFrameWidth - nLeftTextPos ) /
1584  ( MAXLEVEL - nLvl );
1585  }
1586  }
1587  }
1588  }
1589  else
1590  {
1591  bChgBullet = true;
1592  SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_BULLET_LEVEL1 + ( std::min( nLvl, cnNumBullColls ) * 4 )) );
1593  }
1594  }
1595  else
1596  {
1597  // Then it is a numbering
1598 
1599  //JP 21.11.97: The NumLevel is either the DigitLevel or, if the latter is not existent or 0,
1600  // it is determined by the indentation level.
1601 
1602  OUString aPostfix, aPrefix, aNumTypes;
1603  nDigitLevel = GetDigitLevel(*m_pCurTextFrame, nTextStt,
1604  &aPrefix, &aPostfix, &aNumTypes);
1605  if (USHRT_MAX != nDigitLevel)
1606  {
1607  bChgEnum = true;
1608 
1609  // Level 0 and Indentation, determine level by left indentation and default NumIndent
1610  if( !nDigitLevel && nLeftTextPos )
1611  nLvl = std::min( sal_uInt16( nLeftTextPos / lNumberIndent ),
1612  sal_uInt16( MAXLEVEL - 1 ) );
1613  else
1614  nLvl = nDigitLevel;
1615  }
1616 
1617  if( bChgEnum && m_aFlags.bSetNumRule )
1618  {
1619  if( !pCur ) // adjust NumRule if it is new
1620  {
1623 
1624  sal_Int32 nPrefixIdx{ 0 };
1625  if( !nDigitLevel )
1626  {
1627  SwNumFormat aFormat( aRule.Get( nLvl ) );
1628  aFormat.SetPrefix( aPrefix.getToken( 0, u'\x0001', nPrefixIdx ));
1629  aFormat.SetStart( static_cast<sal_uInt16>(aPrefix.getToken( 0, u'\x0001', nPrefixIdx ).toInt32()));
1630  aFormat.SetSuffix( aPostfix.getToken( 0, u'\x0001' ));
1631  aFormat.SetIncludeUpperLevels( 0 );
1632 
1633  if( !aFormat.GetCharFormat() )
1634  aFormat.SetCharFormat( pCFormat );
1635 
1636  if( !aNumTypes.isEmpty() )
1637  aFormat.SetNumberingType(static_cast<SvxNumType>(aNumTypes[ 0 ] - '0'));
1638 
1639  if( bRTL )
1640  aFormat.SetNumAdjust( SvxAdjust::Right );
1641  aRule.Set( nLvl, aFormat );
1642  }
1643  else
1644  {
1645  auto const nSpaceSteps = nLvl ? nLeftTextPos / nLvl : 0;
1646  sal_uInt16 n;
1647  sal_Int32 nPostfixIdx{ 0 };
1648  for( n = 0; n <= nLvl; ++n )
1649  {
1650  SwNumFormat aFormat( aRule.Get( n ) );
1651 
1652  if( !n )
1653  aFormat.SetPrefix( aPrefix.getToken( 0, u'\x0001', nPrefixIdx )); // token 0, read only on first loop
1654  aFormat.SetStart( static_cast<sal_uInt16>(aPrefix.getToken( 0, u'\x0001', nPrefixIdx ).toInt32() ));
1655  aFormat.SetSuffix( aPostfix.getToken( 0, u'\x0001', nPostfixIdx ));
1656  aFormat.SetIncludeUpperLevels( MAXLEVEL );
1657  if( n < aNumTypes.getLength() )
1658  aFormat.SetNumberingType(static_cast<SvxNumType>(aNumTypes[ n ] - '0'));
1659 
1660  aFormat.SetAbsLSpace( nSpaceSteps * n
1661  + lNumberIndent );
1662 
1663  if( !aFormat.GetCharFormat() )
1664  aFormat.SetCharFormat( pCFormat );
1665  if( bRTL )
1666  aFormat.SetNumAdjust( SvxAdjust::Right );
1667 
1668  aRule.Set( n, aFormat );
1669  }
1670 
1671  // Does it fit completely into the frame?
1672  bool bDefStep = nFrameWidth < (nSpaceSteps * MAXLEVEL);
1673  for( ; n < MAXLEVEL; ++n )
1674  {
1675  SwNumFormat aFormat( aRule.Get( n ) );
1676  aFormat.SetIncludeUpperLevels( MAXLEVEL );
1677  if( bDefStep )
1678  aFormat.SetAbsLSpace( nLeftTextPos +
1679  SwNumRule::GetNumIndent(static_cast<sal_uInt8>(n-nLvl)));
1680  else
1681  aFormat.SetAbsLSpace( nSpaceSteps * n
1682  + lNumberIndent );
1683  aRule.Set( n, aFormat );
1684  }
1685  }
1686  }
1687  }
1688  else if( !m_aFlags.bAFormatByInput )
1689  SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_NUM_LEVEL1 + ( std::min( nLvl, cnNumBullColls ) * 4 ) ));
1690  else
1691  bChgEnum = false;
1692  }
1693 
1694  if ( bChgEnum || bChgBullet )
1695  {
1696  m_aDelPam.DeleteMark();
1697  m_aDelPam.GetPoint()->nNode = *m_pCurTextFrame->GetTextNodeForParaProps();
1698 
1699  if( m_aFlags.bSetNumRule )
1700  {
1701  if( m_aFlags.bAFormatByInput )
1702  {
1703  m_aDelPam.SetMark();
1704  SwTextFrame const*const pNextFrame = GetNextNode(false);
1705  assert(pNextFrame);
1706  m_aDelPam.GetMark()->nNode = *pNextFrame->GetTextNodeForParaProps();
1707  m_aDelPam.GetNode(false).GetTextNode()->SetAttrListLevel( nLvl );
1708  }
1709 
1710  const_cast<SwTextNode*>(m_pCurTextFrame->GetTextNodeForParaProps())->SetAttrListLevel(nLvl);
1711 
1712  // start new list
1713  m_pDoc->SetNumRule(m_aDelPam, aRule, true, m_pEditShell->GetLayout());
1714  m_aDelPam.DeleteMark();
1715 
1716  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(TextFrameIndex(0));
1717  }
1718  else
1719  {
1720  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(
1721  bChgEnum ? nTextStt : TextFrameIndex(0));
1722  }
1723  m_aDelPam.SetMark();
1724 
1725  if ( bChgBullet )
1726  nTextStt += TextFrameIndex(2);
1727 
1728  while (nTextStt < TextFrameIndex(rStr.getLength()) && IsSpace(rStr[sal_Int32(nTextStt)]))
1729  nTextStt++;
1730 
1731  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nTextStt);
1732  DeleteSel( m_aDelPam );
1733 
1734  if( !m_aFlags.bSetNumRule )
1735  {
1736  OUString sChgStr('\t');
1737  if( bChgBullet )
1738  sChgStr = OUString(&m_aFlags.cBullet, 1) + sChgStr;
1739  m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, sChgStr );
1740 
1741  SfxItemSet aSet( m_pDoc->GetAttrPool(), aTextNodeSetRange );
1742  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(TextFrameIndex(0));
1743  assert(&m_aDelPam.GetPoint()->nNode.GetNode() == m_pCurTextFrame->GetTextNodeForParaProps());
1744  if( bChgBullet )
1745  {
1746  m_aDelPam.SetMark();
1747  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(TextFrameIndex(1));
1748  SetAllScriptItem( aSet,
1750  m_aFlags.aBulletFont.GetFamilyName(),
1751  m_aFlags.aBulletFont.GetStyleName(),
1752  m_aFlags.aBulletFont.GetPitch(),
1753  m_aFlags.aBulletFont.GetCharSet(),
1754  RES_CHRATR_FONT ) );
1755  m_pDoc->SetFormatItemByAutoFormat( m_aDelPam, aSet );
1756  m_aDelPam.DeleteMark();
1757  nAutoCorrPos = TextFrameIndex(2);
1758  aSet.ClearItem();
1759  }
1761  aTStops.Insert( SvxTabStop( 0 ) );
1762  aSet.Put( aTStops );
1763  assert(&m_aDelPam.GetPoint()->nNode.GetNode() == m_pCurTextFrame->GetTextNodeForParaProps());
1764  m_pDoc->SetFormatItemByAutoFormat( m_aDelPam, aSet );
1765  }
1766  }
1767 
1768  if( bBreak )
1769  {
1770  AutoCorrect( nAutoCorrPos ); /* Offset due to Bullet + Tab */
1771  return;
1772  }
1773 
1774  const SwTextFrame * pNextFrame = GetNextNode();
1775  while (CanJoin(pNextFrame)
1776  && nLvl == CalcLevel(*pNextFrame))
1777  {
1779  bBreak = !IsFastFullLine(*pNextFrame)
1780  || IsBlanksInString(*pNextFrame)
1781  || IsSentenceAtEnd(*pNextFrame);
1782  if (DeleteJoinCurNextPara(pNextFrame))
1783  {
1784  m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, OUString(' ') );
1785  }
1786  if( bBreak )
1787  break;
1788  const SwTextFrame *const pCurrNode = pNextFrame;
1789  pNextFrame = GetNextNode();
1790  if (!pNextFrame || pCurrNode == pNextFrame)
1791  break;
1792  }
1793  DeleteLeadingTrailingBlanks( false );
1794  AutoCorrect( nAutoCorrPos );
1795 }
1796 
1798 {
1800  // Test of contraposition (n words, divided by spaces/tabs, with same indentation in 2nd line)
1801 
1802  // read all succeeding paragraphs that belong to this enumeration
1803  bool bBreak = true;
1804  TextFrameIndex nSpacePos(0);
1805  const sal_Int32 nTextPos = GetBigIndent( nSpacePos );
1806  if( m_bMoreLines )
1807  DelMoreLinesBlanks( true );
1808  else
1809  bBreak = !IsFastFullLine(*m_pCurTextFrame)
1810  || (!nTextPos && IsBlanksInString(*m_pCurTextFrame))
1811  || IsSentenceAtEnd(*m_pCurTextFrame);
1812 
1813  SetColl( static_cast<sal_uInt16>( nTextPos
1816 
1817  if( nTextPos )
1818  {
1819  const OUString& rStr = m_pCurTextFrame->GetText();
1820  bool bInsTab = true;
1821 
1822  if ('\t' == rStr[sal_Int32(nSpacePos) + 1]) // leave tab alone
1823  {
1824  --nSpacePos;
1825  bInsTab = false;
1826  }
1827 
1828  TextFrameIndex nSpaceStt = nSpacePos;
1829  while (nSpaceStt && IsSpace(rStr[sal_Int32(--nSpaceStt)]))
1830  ;
1831  ++nSpaceStt;
1832 
1833  if (bInsTab && '\t' == rStr[sal_Int32(nSpaceStt)]) // leave tab alone
1834  {
1835  ++nSpaceStt;
1836  bInsTab = false;
1837  }
1838 
1839  m_aDelPam.DeleteMark();
1840  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nSpacePos);
1841 
1842  // delete old Spaces, etc.
1843  if( nSpaceStt < nSpacePos )
1844  {
1845  m_aDelPam.SetMark();
1846  *m_aDelPam.GetMark() = m_pCurTextFrame->MapViewToModelPos(nSpaceStt);
1847  DeleteSel( m_aDelPam );
1848  if( bInsTab )
1849  {
1850  m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, OUString('\t') );
1851  }
1852  }
1853  }
1854 
1855  if( !bBreak )
1856  {
1858  SwTextFrameInfo aFInfo( m_pCurTextFrame );
1859  const SwTextFrame * pNextFrame = GetNextNode();
1860  while (CanJoin(pNextFrame) &&
1861  20 < std::abs( static_cast<tools::Long>(nSpaces - aFInfo.SetFrame(
1862  EnsureFormatted(*pNextFrame)).GetLineStart()) )
1863  )
1864  {
1865  bBreak = !IsFastFullLine(*pNextFrame)
1866  || IsBlanksInString(*pNextFrame)
1867  || IsSentenceAtEnd(*pNextFrame);
1868  if (DeleteJoinCurNextPara(pNextFrame))
1869  {
1870  m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, OUString(' ') );
1871  }
1872  if( bBreak )
1873  break;
1874  pNextFrame = GetNextNode();
1875  }
1876  }
1878  AutoCorrect();
1879 }
1880 
1881 void SwAutoFormat::BuildHeadLine( sal_uInt16 nLvl )
1882 {
1883  if( m_aFlags.bWithRedlining )
1884  {
1885  OUString sText(SwViewShell::GetShellRes()->GetAutoFormatNameLst()[
1887  sText = sText.replaceAll( "$(ARG1)", OUString::number( nLvl + 1 ) );
1889  }
1890 
1891  SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + nLvl ), true );
1892  if( m_aFlags.bAFormatByInput )
1893  {
1894  SwTextFormatColl& rNxtColl = m_pCurTextFrame->GetTextNodeForParaProps()->GetTextColl()->GetNextTextFormatColl();
1895 
1896  JoinPrevPara();
1897 
1898  DeleteLeadingTrailingBlanks( true, false );
1899  const SwTextFrame *const pNextFrame = GetNextNode(false);
1900  (void)DeleteJoinCurNextPara(pNextFrame, true);
1901 
1902  m_aDelPam.DeleteMark();
1903  m_aDelPam.GetPoint()->nNode = *GetNextNode(false)->GetTextNodeForParaProps();
1904  m_aDelPam.GetPoint()->nContent.Assign( m_aDelPam.GetContentNode(), 0 );
1905  m_pDoc->SetTextFormatColl( m_aDelPam, &rNxtColl );
1906  }
1907  else
1908  {
1910  AutoCorrect();
1911  }
1912 }
1913 
1916 {
1918  ACFlags aSvxFlags = pATst->GetFlags( );
1919  bool bReplaceQuote( aSvxFlags & ACFlags::ChgQuotes );
1920  bool bReplaceSglQuote( aSvxFlags & ACFlags::ChgSglQuotes );
1921 
1922  if( m_aFlags.bAFormatByInput ||
1923  (!m_aFlags.bAutoCorrect && !bReplaceQuote && !bReplaceSglQuote &&
1924  !m_aFlags.bCapitalStartSentence && !m_aFlags.bCapitalStartWord &&
1925  !m_aFlags.bChgOrdinalNumber && !m_aFlags.bTransliterateRTL &&
1926  !m_aFlags.bChgToEnEmDash && !m_aFlags.bSetINetAttr &&
1927  !m_aFlags.bChgWeightUnderl && !m_aFlags.bAddNonBrkSpace) )
1928  return;
1929 
1930  const OUString* pText = &m_pCurTextFrame->GetText();
1931  if (TextFrameIndex(pText->getLength()) <= nPos)
1932  return;
1933 
1934  bool bGetLanguage = m_aFlags.bChgOrdinalNumber || m_aFlags.bTransliterateRTL ||
1935  m_aFlags.bChgToEnEmDash || m_aFlags.bSetINetAttr ||
1936  m_aFlags.bCapitalStartWord || m_aFlags.bCapitalStartSentence ||
1937  m_aFlags.bAddNonBrkSpace;
1938 
1939  m_aDelPam.DeleteMark();
1940  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(TextFrameIndex(0));
1941 
1942  SwAutoCorrDoc aACorrDoc( *m_pEditShell, m_aDelPam );
1943 
1944  SwTextFrameInfo aFInfo( nullptr );
1945 
1946  TextFrameIndex nSttPos, nLastBlank = nPos;
1947  bool bFirst = m_aFlags.bCapitalStartSentence, bFirstSent = bFirst;
1948  sal_Unicode cChar = 0;
1949  bool bNbspRunNext = false;
1950 
1951  CharClass& rAppCC = GetAppCharClass();
1952 
1953  do {
1954  while (nPos < TextFrameIndex(pText->getLength())
1955  && IsSpace(cChar = (*pText)[sal_Int32(nPos)]))
1956  ++nPos;
1957  if (nPos == TextFrameIndex(pText->getLength()))
1958  break; // that's it
1959 
1960  if( ( ( bReplaceQuote && '\"' == cChar ) ||
1961  ( bReplaceSglQuote && '\'' == cChar ) ) &&
1962  (!nPos || ' ' == (*pText)[sal_Int32(nPos)-1]))
1963  {
1964 
1965  // note: special case symbol fonts !!!
1966  if( !aFInfo.GetFrame() )
1967  aFInfo.SetFrame( GetFrame( *m_pCurTextNd ) );
1968  if( !aFInfo.IsBullet( nPos ))
1969  {
1971  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nPos);
1972  bool bSetHardBlank = false;
1973 
1974  OUString sReplace( pATst->GetQuote( aACorrDoc,
1975  sal_Int32(nPos), cChar, true ));
1976 
1977  m_aDelPam.SetMark();
1978  m_aDelPam.GetPoint()->nContent = m_aDelPam.GetMark()->nContent.GetIndex() + 1;
1979  if( 2 == sReplace.getLength() && ' ' == sReplace[ 1 ])
1980  {
1981  sReplace = sReplace.copy( 0, 1 );
1982  bSetHardBlank = true;
1983  }
1984  m_pDoc->getIDocumentContentOperations().ReplaceRange( m_aDelPam, sReplace, false );
1985 
1986  if( m_aFlags.bWithRedlining )
1987  {
1988  m_aNdIdx = m_aDelPam.GetPoint()->nNode;
1989  m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
1990  m_pCurTextFrame = GetFrame( *m_pCurTextNd );
1991  pText = &m_pCurTextFrame->GetText();
1992  m_aDelPam.SetMark();
1993  aFInfo.SetFrame( nullptr );
1994  }
1995 
1996  nPos += TextFrameIndex(sReplace.getLength() - 1);
1997  m_aDelPam.DeleteMark();
1998  if( bSetHardBlank )
1999  {
2000  m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, OUString(CHAR_HARDBLANK) );
2001  ++nPos;
2002  }
2003  }
2004  }
2005 
2006  bool bCallACorr = false;
2007  int bBreak = 0;
2008  if (nPos && IsSpace((*pText)[sal_Int32(nPos) - 1]))
2009  nLastBlank = nPos;
2010  for (nSttPos = nPos; !bBreak && nPos < TextFrameIndex(pText->getLength()); ++nPos)
2011  {
2012  cChar = (*pText)[sal_Int32(nPos)];
2013  switch (cChar)
2014  {
2015  case '\"':
2016  case '\'':
2017  if( ( cChar == '\"' && bReplaceQuote ) || ( cChar == '\'' && bReplaceSglQuote ) )
2018  {
2019  // consider Symbolfonts!
2020  if( !aFInfo.GetFrame() )
2021  aFInfo.SetFrame( GetFrame( *m_pCurTextNd ) );
2022  if( !aFInfo.IsBullet( nPos ))
2023  {
2025  bool bSetHardBlank = false;
2026  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nPos);
2027  OUString sReplace( pATst->GetQuote( aACorrDoc,
2028  sal_Int32(nPos), cChar, false) );
2029 
2030  if( 2 == sReplace.getLength() && ' ' == sReplace[ 0 ])
2031  {
2032  sReplace = sReplace.copy( 1 );
2033  bSetHardBlank = true;
2034  }
2035 
2036  m_aDelPam.SetMark();
2037  m_aDelPam.GetPoint()->nContent = m_aDelPam.GetMark()->nContent.GetIndex() + 1;
2038  m_pDoc->getIDocumentContentOperations().ReplaceRange( m_aDelPam, sReplace, false );
2039 
2040  if( m_aFlags.bWithRedlining )
2041  {
2042  m_aNdIdx = m_aDelPam.GetPoint()->nNode;
2043  m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
2044  m_pCurTextFrame = GetFrame( *m_pCurTextNd );
2045  pText = &m_pCurTextFrame->GetText();
2046  m_aDelPam.SetMark();
2047  m_aDelPam.DeleteMark();
2048  aFInfo.SetFrame( nullptr );
2049  }
2050 
2051  nPos += TextFrameIndex(sReplace.getLength() - 1);
2052  m_aDelPam.DeleteMark();
2053 
2054  if( bSetHardBlank )
2055  {
2056  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nPos);
2057  m_pDoc->getIDocumentContentOperations().InsertString( m_aDelPam, OUString(CHAR_HARDBLANK) );
2058  ++nPos;
2059  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nPos);
2060  }
2061  }
2062  }
2063  break;
2064  case '*':
2065  case '_':
2066  if( m_aFlags.bChgWeightUnderl )
2067  {
2068  // consider Symbolfonts!
2069  if( !aFInfo.GetFrame() )
2070  aFInfo.SetFrame( GetFrame( *m_pCurTextNd ) );
2071  if( !aFInfo.IsBullet( nPos ))
2072  {
2073  SetRedlineText( '*' == cChar
2076 
2077  sal_Unicode cBlank = nSttPos ? (*pText)[sal_Int32(nSttPos) - 1] : 0;
2078  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nPos);
2079 
2080  if (pATst->FnChgWeightUnderl(aACorrDoc, *pText, sal_Int32(nPos)))
2081  {
2082  if( m_aFlags.bWithRedlining )
2083  {
2084  m_aNdIdx = m_aDelPam.GetPoint()->nNode;
2085  m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
2086  m_pCurTextFrame = GetFrame( *m_pCurTextNd );
2087  pText = &m_pCurTextFrame->GetText();
2088  m_aDelPam.SetMark();
2089  m_aDelPam.DeleteMark();
2090  aFInfo.SetFrame( nullptr );
2091  }
2092  //#125102# in case of the mode RedlineFlags::ShowDelete the ** are still contained in pText
2094  nPos = m_pCurTextFrame->MapModelToViewPos(*m_aDelPam.GetPoint()) - TextFrameIndex(1);
2095  // Was a character deleted before starting?
2096  if (cBlank && cBlank != (*pText)[sal_Int32(nSttPos) - 1])
2097  --nSttPos;
2098  }
2099  }
2100  }
2101  break;
2102  case '/':
2103  if ( m_aFlags.bAddNonBrkSpace )
2104  {
2105  LanguageType eLang = bGetLanguage
2106  ? m_pCurTextFrame->GetLangOfChar(nSttPos, 0, true)
2107  : LANGUAGE_SYSTEM;
2108 
2110  if (pATst->FnAddNonBrkSpace(aACorrDoc, *pText, sal_Int32(nPos), eLang, bNbspRunNext))
2111  --nPos;
2112  }
2113  break;
2114 
2115  case '.':
2116  case '!':
2117  case '?':
2118  if( m_aFlags.bCapitalStartSentence )
2119  bFirstSent = true;
2120  [[fallthrough]];
2121  default:
2122  if (!(rAppCC.isLetterNumeric(*pText, sal_Int32(nPos))
2123  || '/' == cChar )) // '/' should not be a word separator (e.g. '1/2' needs to be handled as one word for replacement)
2124  {
2125  --nPos; // revert ++nPos which was decremented in for loop
2126  ++bBreak;
2127  }
2128  break;
2129  }
2130  }
2131 
2132  if( nPos == nSttPos )
2133  {
2134  if (++nPos == TextFrameIndex(pText->getLength()))
2135  bCallACorr = true;
2136  }
2137  else
2138  bCallACorr = true;
2139 
2140  if( bCallACorr )
2141  {
2142  *m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nPos);
2144  if( m_aFlags.bAutoCorrect &&
2145  aACorrDoc.ChgAutoCorrWord(reinterpret_cast<sal_Int32&>(nSttPos), sal_Int32(nPos), *pATst, nullptr))
2146  {
2147  nPos = m_pCurTextFrame->MapModelToViewPos(*m_aDelPam.GetPoint());
2148 
2149  if( m_aFlags.bWithRedlining )
2150  {
2151  m_aNdIdx = m_aDelPam.GetPoint()->nNode;
2152  m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
2153  m_pCurTextFrame = GetFrame( *m_pCurTextNd );
2154  pText = &m_pCurTextFrame->GetText();
2155  m_aDelPam.SetMark();
2156  m_aDelPam.DeleteMark();
2157  }
2158 
2159  continue; // do not check further
2160  }
2161 
2162  LanguageType eLang = bGetLanguage
2163  ? m_pCurTextFrame->GetLangOfChar(nSttPos, 0, true)
2164  : LANGUAGE_SYSTEM;
2165 
2166  if( m_aFlags.bTransliterateRTL && eLang == LANGUAGE_HUNGARIAN &&
2168  aACorrDoc.TransliterateRTLWord(reinterpret_cast<sal_Int32&>(nSttPos), sal_Int32(nPos)))
2169  {
2170  nPos = m_pCurTextFrame->MapModelToViewPos(*m_aDelPam.GetPoint());
2171  if( m_aFlags.bWithRedlining )
2172  {
2173  m_aNdIdx = m_aDelPam.GetPoint()->nNode;
2174  m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
2175  m_pCurTextFrame = GetFrame( *m_pCurTextNd );
2176  pText = &m_pCurTextFrame->GetText();
2177  m_aDelPam.SetMark();
2178  m_aDelPam.DeleteMark();
2179  }
2180 
2181  continue; // do not check further
2182  }
2183 
2184  if ( m_aFlags.bAddNonBrkSpace )
2185  {
2187  pATst->FnAddNonBrkSpace(aACorrDoc, *pText, sal_Int32(nPos), eLang, bNbspRunNext);
2188  }
2189 
2190  if( ( m_aFlags.bChgOrdinalNumber &&
2192  pATst->FnChgOrdinalNumber(aACorrDoc, *pText, sal_Int32(nSttPos), sal_Int32(nPos), eLang)) ||
2193  ( m_aFlags.bChgToEnEmDash &&
2195  pATst->FnChgToEnEmDash(aACorrDoc, *pText, sal_Int32(nSttPos), sal_Int32(nPos), eLang)) ||
2196  ( m_aFlags.bSetINetAttr &&
2197  (nPos == TextFrameIndex(pText->getLength()) || IsSpace((*pText)[sal_Int32(nPos)])) &&
2199  pATst->FnSetINetAttr(aACorrDoc, *pText, sal_Int32(nLastBlank), sal_Int32(nPos), eLang)))
2200  {
2201  nPos = m_pCurTextFrame->MapModelToViewPos(*m_aDelPam.GetPoint());
2202  }
2203  else
2204  {
2205  // two capital letters at the beginning of a word?
2206  if( m_aFlags.bCapitalStartWord )
2207  {
2209  pATst->FnCapitalStartWord(aACorrDoc, *pText, sal_Int32(nSttPos), sal_Int32(nPos), eLang);
2210  }
2211  // capital letter at the beginning of a sentence?
2212  if( m_aFlags.bCapitalStartSentence && bFirst )
2213  {
2215  pATst->FnCapitalStartSentence(aACorrDoc, *pText, true, sal_Int32(nSttPos), sal_Int32(nPos), eLang);
2216  }
2217 
2218  bFirst = bFirstSent;
2219  bFirstSent = false;
2220 
2221  if( m_aFlags.bWithRedlining )
2222  {
2223  m_aNdIdx = m_aDelPam.GetPoint()->nNode;
2224  m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
2225  m_pCurTextFrame = GetFrame( *m_pCurTextNd );
2226  pText = &m_pCurTextFrame->GetText();
2227  m_aDelPam.SetMark();
2228  m_aDelPam.DeleteMark();
2229  }
2230  }
2231  }
2232  }
2233  while (nPos < TextFrameIndex(pText->getLength()));
2234  ClearRedlineText();
2235 }
2236 
2238  SwNodeIndex const * pSttNd, SwNodeIndex const * pEndNd )
2239  : m_aFlags( rFlags ),
2240  m_aDelPam( pEdShell->GetDoc()->GetNodes().GetEndOfExtras() ),
2241  m_aNdIdx( pEdShell->GetDoc()->GetNodes().GetEndOfExtras(), +1 ),
2242  m_aEndNdIdx( pEdShell->GetDoc()->GetNodes().GetEndOfContent() ),
2243  m_pEditShell( pEdShell ),
2244  m_pDoc( pEdShell->GetDoc() ),
2245  m_pCurTextNd( nullptr ), m_pCurTextFrame( nullptr ),
2246  m_nRedlAutoFormatSeqId( 0 )
2247 {
2248  OSL_ENSURE( (pSttNd && pEndNd) || (!pSttNd && !pEndNd),
2249  "Got no area" );
2250 
2251  if( m_aFlags.bSetNumRule && !m_aFlags.bAFormatByInput )
2252  m_aFlags.bSetNumRule = false;
2253 
2254  bool bReplaceStyles = !m_aFlags.bAFormatByInput || m_aFlags.bReplaceStyles;
2255 
2256  const SwTextFrame * pNextFrame = nullptr;
2257  bool bNxtEmpty = false;
2258  bool bNxtAlpha = false;
2259  sal_uInt16 nNxtLevel = 0;
2260  bool bEmptyLine;
2261 
2262  // set area for autoformatting
2263  if( pSttNd )
2264  {
2265  m_aNdIdx = *pSttNd;
2266  // for GoNextPara, one paragraph prior to that
2267  sw::GotoPrevLayoutTextFrame(m_aNdIdx, m_pEditShell->GetLayout());
2268  m_aEndNdIdx = *pEndNd;
2269  sw::GotoNextLayoutTextFrame(m_aEndNdIdx, m_pEditShell->GetLayout());
2270 
2271  // check the previous TextNode
2272  SwTextFrame const*const pPrevFrame = m_aNdIdx.GetNode().GetTextNode()
2273  ? static_cast<SwTextFrame const*>(m_aNdIdx.GetNode().GetTextNode()->getLayoutFrame(m_pEditShell->GetLayout()))
2274  : nullptr;
2275  bEmptyLine = !pPrevFrame
2276  || IsEmptyLine(*pPrevFrame)
2277  || IsNoAlphaLine(*pPrevFrame);
2278  }
2279  else
2280  bEmptyLine = true; // at document beginning
2281 
2282  m_bEnd = false;
2283 
2284  // set value for percentage display
2285  m_nEndNdIdx = m_aEndNdIdx.GetIndex();
2286 
2287  if( !m_aFlags.bAFormatByInput )
2288  {
2289  m_nEndNdIdx = m_aEndNdIdx.GetIndex();
2290  ::StartProgress( STR_STATSTR_AUTOFORMAT, m_aNdIdx.GetIndex(),
2291  m_nEndNdIdx,
2292  m_pDoc->GetDocShell() );
2293  }
2294 
2295  RedlineFlags eRedlMode = m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags(), eOldMode = eRedlMode;
2296  if( m_aFlags.bWithRedlining )
2297  {
2298  m_pDoc->SetAutoFormatRedline( true );
2299  eRedlMode = RedlineFlags::On | (eOldMode & RedlineFlags::ShowMask);
2300  }
2301  else
2302  eRedlMode = RedlineFlags::Ignore | (eOldMode & RedlineFlags::ShowMask);
2303  m_pDoc->getIDocumentRedlineAccess().SetRedlineFlags( eRedlMode );
2304 
2305  // save undo state (might be turned off)
2306  bool const bUndoState = m_pDoc->GetIDocumentUndoRedo().DoesUndo();
2307 
2308  // If multiple lines, then do not merge with next paragraph
2309  m_bMoreLines = false;
2310 
2311  sal_uInt16 nLastCalcHeadLvl = 0;
2312  sal_uInt16 nLastHeadLvl = USHRT_MAX;
2313  sal_uInt16 nLevel = 0;
2314  sal_uInt16 nDigitLvl = 0;
2315 
2316  // set defaults
2317  SwTextFrameInfo aFInfo( nullptr );
2318 
2319  enum Format_Status
2320  {
2321  READ_NEXT_PARA, // -> ISEND, TST_EMPTY_LINE
2322  TST_EMPTY_LINE, // -> READ_NEXT_PARA, TST_ALPHA_LINE
2323  TST_ALPHA_LINE, // -> READ_NEXT_PARA, GET_ALL_INFO, IS_END
2324  GET_ALL_INFO, // -> READ_NEXT_PARA, IS_ONE_LINE, TST_ENUMERIC, HAS_FMTCOLL
2325  IS_ONE_LINE, // -> READ_NEXT_PARA, TST_ENUMERIC
2326  TST_ENUMERIC, // -> READ_NEXT_PARA, TST_IDENT, TST_NEG_IDENT
2327  TST_IDENT, // -> READ_NEXT_PARA, TST_TXT_BODY
2328  TST_NEG_IDENT, // -> READ_NEXT_PARA, TST_TXT_BODY
2329  TST_TXT_BODY, // -> READ_NEXT_PARA
2330  HAS_FMTCOLL, // -> READ_NEXT_PARA
2331  IS_END
2332  } eStat;
2333 
2334  // This is the automat for autoformatting
2335  eStat = READ_NEXT_PARA;
2336  while( !m_bEnd )
2337  {
2338  switch( eStat )
2339  {
2340  case READ_NEXT_PARA:
2341  {
2342  GoNextPara();
2343  eStat = m_bEnd ? IS_END : TST_EMPTY_LINE;
2344  }
2345  break;
2346 
2347  case TST_EMPTY_LINE:
2348  if (IsEmptyLine(*m_pCurTextFrame))
2349  {
2350  if (m_aFlags.bDelEmptyNode && !HasObjects(*m_pCurTextFrame))
2351  {
2352  bEmptyLine = true;
2353  sal_uLong nOldCnt = m_pDoc->GetNodes().Count();
2354  DelEmptyLine();
2355  // Was there really a deletion of a node?
2356  if( nOldCnt != m_pDoc->GetNodes().Count() )
2357  {
2358  // do not skip the next paragraph
2359  sw::GotoPrevLayoutTextFrame(m_aNdIdx, m_pEditShell->GetLayout());
2360  }
2361  }
2362  eStat = READ_NEXT_PARA;
2363  }
2364  else
2365  eStat = TST_ALPHA_LINE;
2366  break;
2367 
2368  case TST_ALPHA_LINE:
2369  if (IsNoAlphaLine(*m_pCurTextFrame))
2370  {
2371  // recognize a table definition +---+---+
2372  if( m_aFlags.bAFormatByInput && m_aFlags.bCreateTable && DoTable() )
2373  {
2374  //JP 30.09.96: DoTable() builds on PopCursor and MoveCursor after AutoFormat!
2376  *pEdShell->GetCursor() = m_aDelPam;
2377  pEdShell->Push();
2378 
2379  eStat = IS_END;
2380  break;
2381  }
2382 
2383  // Check for 3 "---" or "===". In this case, the previous paragraph should be
2384  // underlined and the current be deleted!
2385  if( !DoUnderline() && bReplaceStyles )
2386  {
2387  SetColl( RES_POOLCOLL_STANDARD, true );
2388  bEmptyLine = true;
2389  }
2390  eStat = READ_NEXT_PARA;
2391  }
2392  else
2393  eStat = GET_ALL_INFO;
2394  break;
2395 
2396  case GET_ALL_INFO:
2397  {
2398  if (m_pCurTextFrame->GetTextNodeForParaProps()->GetNumRule())
2399  {
2400  // do nothing in numbering, go to next
2401  bEmptyLine = false;
2402  eStat = READ_NEXT_PARA;
2403  // delete all blanks at beginning/end and in between
2404  //JP 29.04.98: first only "all in between"
2406  break;
2407  }
2408 
2409  aFInfo.SetFrame( m_pCurTextFrame );
2410 
2411  // so far: if there were templates assigned, keep these and go to next node
2412  sal_uInt16 nPoolId = m_pCurTextFrame->GetTextNodeForParaProps()->GetTextColl()->GetPoolFormatId();
2413  if( IsPoolUserFormat( nPoolId )
2414  ? !m_aFlags.bChgUserColl
2415  : ( RES_POOLCOLL_STANDARD != nPoolId &&
2416  ( !m_aFlags.bAFormatByInput ||
2417  (RES_POOLCOLL_TEXT_MOVE != nPoolId &&
2418  RES_POOLCOLL_TEXT != nPoolId )) ))
2419  {
2420  eStat = HAS_FMTCOLL;
2421  break;
2422  }
2423 
2424  // check for hard spaces or LRSpaces set by the template
2425  if( IsPoolUserFormat( nPoolId ) ||
2426  RES_POOLCOLL_STANDARD == nPoolId )
2427  {
2428  short nSz;
2429  SvxLRSpaceItem const * pLRSpace;
2430  if (SfxItemState::SET == m_pCurTextFrame->GetTextNodeForParaProps()->GetSwAttrSet().
2431  GetItemState( RES_LR_SPACE, true,
2432  reinterpret_cast<const SfxPoolItem**>(&pLRSpace) ) &&
2433  ( 0 != (nSz = pLRSpace->GetTextFirstLineOffset()) ||
2434  0 != pLRSpace->GetTextLeft() ) )
2435  {
2436  // exception: numbering/enumeration can have an indentation
2437  if (IsEnumericChar(*m_pCurTextFrame))
2438  {
2439  nLevel = CalcLevel(*m_pCurTextFrame, &nDigitLvl);
2440  if( nLevel >= MAXLEVEL )
2441  nLevel = MAXLEVEL-1;
2442  BuildEnum( nLevel, nDigitLvl );
2443  eStat = READ_NEXT_PARA;
2444  break;
2445  }
2446 
2447  // never merge (maybe only indent as exception)
2448  m_bMoreLines = true;
2449 
2450  if( bReplaceStyles )
2451  {
2452  // then use one of our templates
2453  if( 0 < nSz ) // positive 1st line indentation
2454  BuildIndent();
2455  else if( 0 > nSz ) // negative 1st line indentation
2456  BuildNegIndent( aFInfo.GetLineStart() );
2457  else if( pLRSpace->GetTextLeft() ) // is indentation
2458  BuildTextIndent();
2459  }
2460  eStat = READ_NEXT_PARA;
2461  break;
2462  }
2463  }
2464 
2465  nLevel = CalcLevel( *m_pCurTextFrame, &nDigitLvl );
2466  m_bMoreLines = !IsOneLine(*m_pCurTextFrame);
2467  // note: every use of pNextFrame in following states, until the
2468  // next READ_NEXT_PARA, relies on this update
2469  pNextFrame = GetNextNode();
2470  if (pNextFrame)
2471  {
2472  bNxtEmpty = IsEmptyLine(*pNextFrame);
2473  bNxtAlpha = IsNoAlphaLine(*pNextFrame);
2474  nNxtLevel = CalcLevel(*pNextFrame);
2475 
2476  if (!bEmptyLine && HasBreakAttr(*m_pCurTextFrame))
2477  bEmptyLine = true;
2478  if (!bNxtEmpty && HasBreakAttr(*pNextFrame))
2479  bNxtEmpty = true;
2480 
2481  }
2482  else
2483  {
2484  bNxtEmpty = false;
2485  bNxtAlpha = false;
2486  nNxtLevel = 0;
2487  }
2488  eStat = !m_bMoreLines ? IS_ONE_LINE : TST_ENUMERIC;
2489  }
2490  break;
2491 
2492  case IS_ONE_LINE:
2493  {
2494  eStat = TST_ENUMERIC;
2495  if( !bReplaceStyles )
2496  break;
2497 
2498  const OUString sClrStr( DelLeadingBlanks(m_pCurTextFrame->GetText()) );
2499 
2500  if( sClrStr.isEmpty() )
2501  {
2502  bEmptyLine = true;
2503  eStat = READ_NEXT_PARA;
2504  break; // read next paragraph
2505  }
2506 
2507  // check if headline
2508  if (!bEmptyLine || !IsFirstCharCapital(*m_pCurTextFrame)
2509  || IsBlanksInString(*m_pCurTextFrame))
2510  break;
2511 
2512  bEmptyLine = false;
2513  const OUString sEndClrStr( DelTrailingBlanks(sClrStr) );
2514  const sal_Unicode cLast = sEndClrStr[sEndClrStr.getLength() - 1];
2515 
2516  // not, then check if headline
2517  if( ':' == cLast )
2518  {
2519  BuildHeadLine( 2 );
2520  eStat = READ_NEXT_PARA;
2521  break;
2522  }
2523  else if( 256 <= cLast || !strchr( ",.;", cLast ) )
2524  {
2525  if( bNxtEmpty || bNxtAlpha
2526  || (pNextFrame && IsEnumericChar(*pNextFrame)))
2527  {
2528 
2529  // one level below?
2530  if( nLevel >= MAXLEVEL )
2531  nLevel = MAXLEVEL-1;
2532 
2533  if( USHRT_MAX == nLastHeadLvl )
2534  nLastHeadLvl = 0;
2535  else if( nLastCalcHeadLvl < nLevel )
2536  {
2537  if( nLastHeadLvl+1 < MAXLEVEL )
2538  ++nLastHeadLvl;
2539  }
2540  // one level above?
2541  else if( nLastCalcHeadLvl > nLevel )
2542  {
2543  if( nLastHeadLvl )
2544  --nLastHeadLvl;
2545  }
2546  nLastCalcHeadLvl = nLevel;
2547 
2548  if( m_aFlags.bAFormatByInput )
2549  BuildHeadLine( nLevel );
2550  else
2551  BuildHeadLine( nLastHeadLvl );
2552  eStat = READ_NEXT_PARA;
2553  break;
2554  }
2555  }
2556  }
2557  break;
2558 
2559  case TST_ENUMERIC:
2560  {
2561  bEmptyLine = false;
2562  if (IsEnumericChar(*m_pCurTextFrame))
2563  {
2564  if( nLevel >= MAXLEVEL )
2565  nLevel = MAXLEVEL-1;
2566  BuildEnum( nLevel, nDigitLvl );
2567  eStat = READ_NEXT_PARA;
2568  }
2569  else if( bReplaceStyles )
2570  eStat = nLevel ? TST_IDENT : TST_NEG_IDENT;
2571  else
2572  eStat = READ_NEXT_PARA;
2573  }
2574  break;
2575 
2576  case TST_IDENT:
2577  // Spaces at the beginning, check again for indentation
2578  if( m_bMoreLines && nLevel )
2579  {
2580  SwTwips nSz = aFInfo.GetFirstIndent();
2581  if( 0 < nSz ) // positive 1st line indentation
2582  BuildIndent();
2583  else if( 0 > nSz ) // negative 1st line indentation
2584  BuildNegIndent( aFInfo.GetLineStart() );
2585  else // is indentation
2586  BuildTextIndent();
2587  eStat = READ_NEXT_PARA;
2588  }
2589  else if (nLevel && pNextFrame &&
2590  !bNxtEmpty && !bNxtAlpha && !nNxtLevel &&
2591  !IsEnumericChar(*pNextFrame))
2592  {
2593  // is an indentation
2594  BuildIndent();
2595  eStat = READ_NEXT_PARA;
2596  }
2597  else
2598  eStat = TST_TXT_BODY;
2599  break;
2600 
2601  case TST_NEG_IDENT:
2602  // no spaces at the beginning, check again for negative indentation
2603  {
2604  if( m_bMoreLines && !nLevel )
2605  {
2606  SwTwips nSz = aFInfo.GetFirstIndent();
2607  if( 0 < nSz ) // positive 1st line indentation
2608  BuildIndent();
2609  else if( 0 > nSz ) // negative 1st line indentation
2610  BuildNegIndent( aFInfo.GetLineStart() );
2611  else // is _no_ indentation
2612  BuildText();
2613  eStat = READ_NEXT_PARA;
2614  }
2615  else if (!nLevel && pNextFrame &&
2616  !bNxtEmpty && !bNxtAlpha && nNxtLevel &&
2617  !IsEnumericChar(*pNextFrame))
2618  {
2619  // is a negative indentation
2620  BuildNegIndent( aFInfo.GetLineStart() );
2621  eStat = READ_NEXT_PARA;
2622  }
2623  else
2624  eStat = TST_TXT_BODY;
2625  }
2626  break;
2627 
2628  case TST_TXT_BODY:
2629  {
2630  if( m_bMoreLines )
2631  {
2632  SwTwips nSz = aFInfo.GetFirstIndent();
2633  if( 0 < nSz ) // positive 1st line indentation
2634  BuildIndent();
2635  else if( 0 > nSz ) // negative 1st line indentation
2636  BuildNegIndent( aFInfo.GetLineStart() );
2637  else if( nLevel ) // is indentation
2638  BuildTextIndent();
2639  else
2640  BuildText();
2641  }
2642  else if( nLevel )
2643  BuildTextIndent();
2644  else
2645  BuildText();
2646  eStat = READ_NEXT_PARA;
2647  }
2648  break;
2649 
2650  case HAS_FMTCOLL:
2651  {
2652  // so far: if there were templates assigned, keep these and go to next node
2653  bEmptyLine = false;
2654  eStat = READ_NEXT_PARA;
2655  // delete all blanks at beginning/end and in between
2656  //JP 29.04.98: first only "all in between"
2658 
2659  // handle hard attributes
2660  if (m_pCurTextFrame->GetTextNodeForParaProps()->HasSwAttrSet())
2661  {
2662  short nSz;
2663  SvxLRSpaceItem const * pLRSpace;
2664  if( bReplaceStyles &&
2665  SfxItemState::SET == m_pCurTextFrame->GetTextNodeForParaProps()->GetSwAttrSet().
2666  GetItemState( RES_LR_SPACE, false,
2667  reinterpret_cast<const SfxPoolItem**>(&pLRSpace) ) &&
2668  ( 0 != (nSz = pLRSpace->GetTextFirstLineOffset()) ||
2669  0 != pLRSpace->GetTextLeft() ) )
2670  {
2671  // then use one of our templates
2672  if( 0 < nSz ) // positive 1st line indentation
2673  BuildIndent();
2674  else if( 0 > nSz ) // negative 1st line indentation
2675  {
2676  BuildNegIndent( aFInfo.GetLineStart() );
2677  }
2678  else if( pLRSpace->GetTextLeft() ) // is indentation
2679  BuildTextIndent();
2680  else
2681  BuildText();
2682  }
2683  }
2684  }
2685  break;
2686 
2687  case IS_END:
2688  m_bEnd = true;
2689  break;
2690  }
2691  }
2692 
2693  if( m_aFlags.bWithRedlining )
2694  m_pDoc->SetAutoFormatRedline( false );
2695  m_pDoc->getIDocumentRedlineAccess().SetRedlineFlags( eOldMode );
2696 
2697  // restore undo (in case it has been changed)
2698  m_pDoc->GetIDocumentUndoRedo().DoUndo(bUndoState);
2699 
2700  // disable display of percentage again
2701  if( !m_aFlags.bAFormatByInput )
2702  ::EndProgress( m_pDoc->GetDocShell() );
2703 }
2704 
2706 {
2707  std::unique_ptr<SwWait> pWait;
2708 
2709  CurrShell aCurr( this );
2710  StartAllAction();
2712 
2713  SvxSwAutoFormatFlags aAFFlags; // use default values or add params?
2714  if( pAFlags )
2715  {
2716  aAFFlags = *pAFlags;
2717  if( !aAFFlags.bAFormatByInput )
2718  pWait.reset(new SwWait( *GetDoc()->GetDocShell(), true ));
2719  }
2720 
2721  SwPaM* pCursor = GetCursor();
2722  // There are more than one or a selection is open
2723  if( pCursor->GetNext() != pCursor || pCursor->HasMark() )
2724  {
2725  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
2726  {
2727  if( rPaM.HasMark() )
2728  {
2729  SwAutoFormat aFormat( this, aAFFlags, &(rPaM.Start()->nNode),
2730  &(rPaM.End()->nNode) );
2731  }
2732  }
2733  }
2734  else
2735  {
2736  SwAutoFormat aFormat( this, aAFFlags );
2737  }
2738 
2740  EndAllAction();
2741 }
2742 
2744 {
2745  CurrShell aCurr( this );
2746  SwPaM* pCursor = GetCursor();
2747  if( pCursor->IsMultiSelection() || !pCursor->Move( fnMoveBackward, GoInNode ) )
2748  return;
2749 
2750  StartAllAction();
2752 
2753  bool bRange = false;
2754  pCursor->SetMark();
2755  SwIndex* pContent = &pCursor->GetMark()->nContent;
2756  if( pContent->GetIndex() )
2757  {
2758  *pContent = 0;
2759  bRange = true;
2760  }
2761  else
2762  {
2763  // then go one node backwards
2764  SwNodeIndex aNdIdx(pCursor->GetMark()->nNode);
2766  SwTextNode* pTextNd = aNdIdx.GetNode().GetTextNode();
2767  if (pTextNd && !pTextNd->GetText().isEmpty())
2768  {
2769  pContent->Assign( pTextNd, 0 );
2770  pCursor->GetMark()->nNode = aNdIdx;
2771  bRange = true;
2772  }
2773  }
2774 
2775  if( bRange )
2776  {
2777  Push(); // save cursor
2778 
2779  SvxSwAutoFormatFlags aAFFlags = *GetAutoFormatFlags(); // use default values so far
2780 
2781  SwAutoFormat aFormat( this, aAFFlags, &pCursor->GetMark()->nNode,
2782  &pCursor->GetPoint()->nNode );
2784  if( pACorr && !pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2785  ACFlags::AddNonBrkSpace | ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
2786  ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | ACFlags::Autocorrect ))
2787  pACorr = nullptr;
2788 
2789  if( pACorr )
2790  AutoCorrect( *pACorr,false, u'\0' );
2791 
2792  //JP 30.09.96: DoTable() builds on PopCursor and MoveCursor!
2794  pCursor = GetCursor();
2795  }
2796  pCursor->DeleteMark();
2797  pCursor->Move( fnMoveForward, GoInNode );
2798 
2800  EndAllAction();
2801 
2802 }
2803 
2805 {
2806  if (!s_pAutoFormatFlags)
2808 
2809  return s_pAutoFormatFlags;
2810 }
2811 
2813 {
2814  SvxSwAutoFormatFlags* pEditFlags = GetAutoFormatFlags();
2815 
2816  pEditFlags->bSetNumRule = pFlags->bSetNumRule;
2817  pEditFlags->bChgEnumNum = pFlags->bChgEnumNum;
2818  pEditFlags->bSetBorder = pFlags->bSetBorder;
2819  pEditFlags->bCreateTable = pFlags->bCreateTable;
2820  pEditFlags->bReplaceStyles = pFlags->bReplaceStyles;
2821  pEditFlags->bAFormatByInpDelSpacesAtSttEnd =
2825 
2826  //JP 15.12.98: copy BulletChar and Font into "normal" ones
2827  // because AutoFormat can only work with the latter!
2828  pEditFlags->cBullet = pFlags->cByInputBullet;
2829  pEditFlags->aBulletFont = pFlags->aByInputBulletFont;
2830  pEditFlags->cByInputBullet = pFlags->cByInputBullet;
2831  pEditFlags->aByInputBulletFont = pFlags->aByInputBulletFont;
2832 }
2833 
2834 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual SwCharFormat * GetCharFormatFromPool(sal_uInt16 nId)=0
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:338
static SwTwips GetLineStart(const SwTextCursor &rLine)
Definition: frminf.cxx:89
void AutoCorrect(TextFrameIndex nSttPos=TextFrameIndex(0))
execute AutoCorrect on current TextNode
Definition: autofmt.cxx:1915
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:690
void merge(RingContainer< value_type > aDestRing)
Merges two ring containers.
Definition: ring.hxx:182
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:151
std::shared_ptr< SwUnoCursor > CreateUnoCursor(const SwPosition &rPos, bool bTableCursor=false)
Definition: doc.cxx:1779
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(93)
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:44
void DeleteMark()
Definition: pam.hxx:177
void SetBorderLineStyle(SvxBorderLineStyle nNew)
bool Insert(const SvxTabStop &rTab)
sal_uLong GetIndex() const
Definition: node.hxx:290
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
sal_uLong Count() const
Definition: ndarr.hxx:142
bool FnChgToEnEmDash(SvxAutoCorrDoc &, const OUString &, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang)
bool bAFormatByInpDelSpacesBetweenLines
sal_Int32 getCharacterType(const OUString &rStr, sal_Int32 nPos) const
Represents the style of a paragraph.
Definition: fmtcol.hxx:55
void SetWidth(tools::Long nWidth)
static OUString DelTrailingBlanks(const OUString &rStr)
Definition: autofmt.cxx:697
static SvxAutoCorrCfg & Get()
bool GetRanges(std::vector< std::shared_ptr< SwUnoCursor >> &rRanges, SwDoc &rDoc, SwPaM const &rDelPam)
Definition: autofmt.cxx:1117
Marks a position in the document model.
Definition: pam.hxx:35
constexpr TypedWhichId< SvxTabStopItem > RES_PARATR_TABSTOP(68)
bool isAlpha(const OUString &rStr, sal_Int32 nPos) const
bool IsSectionNode() const
Definition: node.hxx:652
const OUString & GetFamilyName() const
bool IsMultiSelection() const
Definition: pam.hxx:272
void DelEmptyLine(bool bTstNextPara=true)
Definition: autofmt.cxx:1245
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:189
SvxAdjust GetAdjust() const
LanguageType GetLangOfChar(TextFrameIndex nIndex, sal_uInt16 nScript, bool bNoChar=false) const
Definition: txtfrm.cxx:1333
sal_uInt32 sal_UCS4
#define STR_AUTOFMTREDL_NON_BREAK_SPACE
Definition: comcore.hxx:44
const OUString & GetText() const
Definition: ndtxt.hxx:211
static ShellResource * GetShellRes()
Definition: viewsh.cxx:2504
void SetColl(sal_uInt16 nId, bool bHdLineOrText=false)
Definition: autofmt.cxx:999
SwDocShell * GetDocShell()
Definition: doc.hxx:1348
static bool isLetterType(sal_Int32 nType)
const OUString & GetStyleName() const
sal_uInt16 CalcLevel(const SwTextFrame &, sal_uInt16 *pDigitLvl=nullptr) const
Definition: autofmt.cxx:431
bool FnChgOrdinalNumber(SvxAutoCorrDoc &, const OUString &, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang)
sal_uInt16 const aTextNodeSetRange[]
Definition: init.cxx:170
void BuildTextIndent()
Definition: autofmt.cxx:1391
SwNodeIndex nNode
Definition: pam.hxx:37
void SetCompletePaint() const
Definition: frame.hxx:972
virtual void InsertItemSet(const SwPaM &rRg, const SfxItemSet &, const SetAttrMode nFlags=SetAttrMode::DEFAULT, SwRootFrame const *pLayout=nullptr)=0
void ClearRedlineText()
Definition: autofmt.cxx:212
SAL_DLLPRIVATE void DeleteSel(SwPaM &rPam, bool *pUndo=nullptr)
Definition: eddel.cxx:34
sal_uIntPtr sal_uLong
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_LANGUAGE(10)
const SwRect & getFramePrintArea() const
Definition: frame.hxx:178
const SwPosition * GetMark() const
Definition: pam.hxx:209
void SetPrefix(const OUString &rSet)
LanguageType GetLanguage(SfxItemSet const &aSet, sal_uInt16 nLangWhichId)
Definition: langhelper.cxx:399
SVX_NUM_CHARS_UPPER_LETTER
sw::MergedPara * GetMergedPara()
Definition: txtfrm.hxx:441
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1192
sal_Int64 n
Definition: doc.hxx:184
helper class to disable creation of an action by a callback event in particular, change event from a ...
Definition: rootfrm.hxx:441
void AutoCorrect(SvxAutoCorrect &rACorr, bool bInsertMode, sal_Unicode cChar)
Call AutoCorrect.
Definition: edws.cxx:255
bool IsNoAlphaLine(const SwTextFrame &) const
Definition: autofmt.cxx:499
#define CHAR_HARDBLANK
Definition: swtypes.hxx:164
bool IsPoolUserFormat(sal_uInt16 nId)
Definition: poolfmt.hxx:86
SwUndoId EndUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Closes parenthesis of nUndoId, not used by UI.
Definition: edws.cxx:234
void DeleteSel(SwPaM &rPam)
Definition: autofmt.cxx:1164
constexpr TypedWhichId< SvxFormatBreakItem > RES_BREAK(94)
static bool HasObjects(const SwTextFrame &)
Definition: autofmt.cxx:340
::sw::DocumentRedlineManager const & GetDocumentRedlineManager() const
Definition: doc.cxx:345
SwDoc * m_pDoc
Definition: autofmt.cxx:93
SwNode & GetNode() const
Definition: ndindex.hxx:119
long SwTwips
Definition: swtypes.hxx:49
static bool HasSelBlanks(SwTextFrame const *const pStartFrame, TextFrameIndex &rStartIndex, SwTextFrame const *const pEndFrame, TextFrameIndex &rEndIndex)
Definition: autofmt.cxx:1033
void EndProgress(SwDocShell const *pDocShell)
Definition: mainwn.cxx:92
OUString GetUniqueNumRuleName(const OUString *pChkStr=nullptr, bool bAutoNum=true) const
Definition: docnum.cxx:2492
Dialog to specify the properties of date form field.
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:144
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1787
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
void SetIncludeUpperLevels(sal_uInt8 nSet)
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1283
SwTextFrame * EnsureFormatted(SwTextFrame const &) const
Definition: autofmt.cxx:237
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:315
sal_Int32 GetBigIndent(TextFrameIndex &rFndPos, const SwTextFrame *pNextFrame) const
Definition: frminf.cxx:239
void EndAllAction()
Definition: edws.cxx:97
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_FONT(7)
static sal_Int32 GetLeadingBlanks(const OUString &rStr)
Definition: autofmt.cxx:710
void MoveTo(value_type *pDestRing)
Removes this item from its current ring container and adds it to another ring container.
Definition: ring.hxx:135
bool isFrameAreaDefinitionValid() const
Definition: frame.hxx:169
#define DEF_LINE_WIDTH_1
#define LANGUAGE_HUNGARIAN
FontFamily GetFamilyType()
const SwSection & GetSection() const
Definition: node.hxx:549
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
bool bAFormatByInpDelSpacesAtSttEnd
const sal_Unicode cStarSymbolEmDash
Definition: autofmt.cxx:77
#define STR_AUTOFMTREDL_DEL_MORELINES
Definition: comcore.hxx:43
void FnCapitalStartSentence(SvxAutoCorrDoc &, const OUString &, bool bNormalPos, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang)
bool isLetterNumeric(const OUString &rStr, sal_Int32 nPos) const
sal_uInt16 sal_Unicode
#define STR_AUTOFMTREDL_CPTL_STT_WORD
Definition: comcore.hxx:25
void SetRedlineText_(sal_uInt16 nId)
Definition: autofmt.cxx:257
void JoinPrevPara()
join with the previous paragraph
Definition: autofmt.cxx:1334
bool IsBullet(TextFrameIndex nTextPos) const
Definition: frminf.cxx:195
void StartProgress(const char *pMessResId, tools::Long nStartValue, tools::Long nEndValue, SwDocShell *pDocShell)
Definition: mainwn.cxx:52
ACFlags
SwIndex nContent
Definition: pam.hxx:38
const SwRect & getFrameArea() const
Definition: frame.hxx:177
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
#define STR_AUTOFMTREDL_USE_REPLACE
Definition: comcore.hxx:24
bool CanJoin(const SwTextFrame *pNextFrame) const
Definition: autofmt.cxx:186
bool SetTextFormatColl(const SwPaM &rRg, SwTextFormatColl *pFormat, const bool bReset=true, const bool bResetListAttrs=false, SwRootFrame const *pLayout=nullptr)
Add 4th optional parameter .
Definition: docfmt.cxx:1072
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:426
#define STR_AUTOFMTREDL_TYPO
Definition: comcore.hxx:27
constexpr TypedWhichId< SwFormatDrop > RES_PARATR_DROP(70)
void SetAllScriptItem(SfxItemSet &rSet, const SfxPoolItem &rItem)
Definition: poolfmt.cxx:39
bool IsFilled(const sal_uInt8 nPercent) const
Definition: frminf.cxx:76
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
SVX_NUM_ARABIC
void GoNextPara()
Definition: autofmt.cxx:293
const sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:95
virtual void DoUndo(bool const bDoUndo)=0
Enable/Disable Undo.
For internal use only.
sal_uInt16 GetDigitLevel(const SwTextFrame &rFrame, TextFrameIndex &rPos, OUString *pPrefix=nullptr, OUString *pPostfix=nullptr, OUString *pNumTypes=nullptr) const
Definition: autofmt.cxx:750
void Width(tools::Long nNew)
Definition: swrect.hxx:187
SVX_NUM_ROMAN_UPPER
void SetFormatItemByAutoFormat(const SwPaM &rPam, const SfxItemSet &)
Definition: docfmt.cxx:1807
sal_uInt8 GetAutoFormatLvl() const
Definition: node.hxx:138
std::unique_ptr< CharClass > m_pCharClass
Definition: autofmt.cxx:97
void DelMoreLinesBlanks(bool bWithLineBreaks=false)
when using multiline paragraphs delete the "left" and/or "right" margins
Definition: autofmt.cxx:1297
#define STR_AUTOFMTREDL_SET_TMPL_TEXT
Definition: comcore.hxx:37
Numbering symbols.
Definition: poolfmt.hxx:117
SVX_NUM_ROMAN_LOWER
bool IsProtectFlag() const
Definition: section.hxx:188
SwDoc * GetDoc() const
Definition: viewsh.hxx:281
void GotoNextLayoutTextFrame(SwNodeIndex &rIndex, SwRootFrame const *const pLayout)
Definition: docnum.cxx:1474
Text body indent.
Definition: poolfmt.hxx:253
RedlineFlags on.
bool IsEmpty() const
Definition: swrect.hxx:292
virtual bool DoesUndo() const =0
Is Undo enabled?
void BuildEnum(sal_uInt16 nLvl, sal_uInt16 nDigitLevel)
Definition: autofmt.cxx:1471
SwPaM * GetNext()
Definition: pam.hxx:264
SwTwips GetFirstIndent() const
Definition: frminf.cxx:207
sal_uInt16 GetPoolFormatId() const
Get and set Pool style IDs.
Definition: format.hxx:143
void FnCapitalStartWord(SvxAutoCorrDoc &, const OUString &, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang)
LanguageType m_eCharClassLang
Definition: autofmt.cxx:98
SwRect GetPaintSwRect()
Page number etc.
Definition: frmpaint.cxx:445
SwShellCursor * GetCursor_()
Definition: crsrsh.hxx:328
const short lBulletIndent
Definition: swtypes.hxx:103
SVX_NUM_CHAR_SPECIAL
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:448
const SwTextFrame * GetNextNode(bool isCheckEnd=true) const
Definition: autofmt.cxx:358
bool FrameContainsNode(SwContentFrame const &rFrame, sal_uLong nNodeIndex)
Definition: txtfrm.cxx:284
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:451
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:501
static bool IsBlanksInString(const SwTextFrame &)
Definition: autofmt.cxx:409
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1293
virtual bool InsertString(const SwPaM &rRg, const OUString &, const SwInsertFlags nInsertMode=SwInsertFlags::EMPTYEXPAND)=0
Insert string into existing text node at position rRg.Point().
tools::Long GetTextLeft() const
sal_Unicode GetQuote(sal_Unicode cInsChar, bool bSttQuote, LanguageType eLang) const
sal_uLong m_nEndNdIdx
Definition: autofmt.cxx:96
void DeleteSelImpl(SwPaM &rDelPam, SwPaM &rPamToCorrect)
Definition: autofmt.cxx:1180
#define STR_AUTOFMTREDL_SET_TMPL_TEXT_INDENT
Definition: comcore.hxx:40
SVX_NUM_CHARS_LOWER_LETTER
#define DEF_LINE_WIDTH_3
bool IsInRightToLeftText() const
Definition: crsrsh.cxx:3402
TextFrameIndex MapModelToViewPos(SwPosition const &rPos) const
Definition: txtfrm.cxx:1259
FontPitch GetPitch()
void AutoFormat(const SvxSwAutoFormatFlags *pAFlags)
Set our styles according to the respective rules.
Definition: autofmt.cxx:2705
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
bool IsOneLine(const SwTextFrame &) const
Definition: autofmt.cxx:369
SvxAdjust
bool GoInNode(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:954
bool bAFormatDelSpacesBetweenLines
uno_Any a
void SetBulletFont(const vcl::Font *pFont)
#define STR_AUTOFMTREDL_DEL_EMPTY_PARA
Definition: comcore.hxx:23
bool IsOneLine() const
Definition: frminf.cxx:55
const SwPosition * GetPoint() const
Definition: pam.hxx:207
void AutoFormatBySplitNode()
Definition: autofmt.cxx:2743
#define STR_AUTOFMTREDL_BOLD
Definition: comcore.hxx:31
#define STR_AUTOFMTREDL_FRACTION
Definition: comcore.hxx:32
const vcl::Font & GetDefBulletFont()
retrieve font used for the default bullet list characters
Definition: number.cxx:1320
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
#define LANGUAGE_SYSTEM
void Push()
store a copy of the current cursor on the cursor stack
Definition: crsrsh.cxx:2236
Text body.
Definition: poolfmt.hxx:250
sal_Int32 GetBigIndent(TextFrameIndex &rCurrentSpacePos) const
Definition: autofmt.cxx:482
SvxAutoCorrect * GetAutoCorrect()
bool FnAddNonBrkSpace(SvxAutoCorrDoc &, const OUString &, sal_Int32 nEndPos, LanguageType eLang, bool &io_bNbspRunNext)
bool IsHiddenFlag() const
Definition: section.hxx:187
SwNodeIndex m_aNdIdx
Definition: autofmt.cxx:89
SwContentNode * GetContentNode()
Definition: node.hxx:623
vector_type::size_type size_type
Definition: docary.hxx:228
const short lBulletFirstLineOffset
Definition: swtypes.hxx:104
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
tools::Long GetLeft() const
SwUndoId StartUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Undo: set up Undo parenthesis, return nUndoId of this parenthesis.
Definition: edws.cxx:223
const SvxAdjustItem & GetAdjust(bool=true) const
Definition: paratr.hxx:180
Marks a character position inside a document model node.
Definition: index.hxx:33
float u
::rtl::Reference< Content > pContent
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2779
bool FnSetINetAttr(SvxAutoCorrDoc &, const OUString &, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang)
const sal_Unicode pBulletChar[6]
Definition: autofmt.cxx:73
short GetTextFirstLineOffset() const
bool SetRedlineText(sal_uInt16 nId)
Definition: autofmt.cxx:207
SwTextFrame * GetFormatted(bool bForceQuickFormat=false)
In case the SwLineLayout was cleared out of the s_pTextCache, recreate it.
Definition: txtfrm.cxx:3353
Marks a node in the document model.
Definition: ndindex.hxx:31
bool IsEndNode() const
Definition: node.hxx:640
virtual bool ReplaceRange(SwPaM &rPam, const OUString &rNewStr, const bool bRegExReplace)=0
Replace selected range in a TextNode with string.
CharClass & GetCharClass(LanguageType eLang) const
Definition: autofmt.cxx:118
sal_uInt16 m_nRedlAutoFormatSeqId
Definition: autofmt.cxx:100
bool HasSwAttrSet() const
Definition: node.hxx:452
ring_container GetRingContainer()
Definition: ring.hxx:240
void SetDistance(sal_uInt16 nNew, SvxBoxItemLine nLine)
static sal_uInt16 GetNumIndent(sal_uInt8 nLvl)
Definition: number.cxx:161
OUString lowercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
vcl::Font aByInputBulletFont
void SetTextFormatCollByAutoFormat(const SwPosition &rPos, sal_uInt16 nPoolId, const SfxItemSet *pSet)
Definition: docfmt.cxx:1759
SwEditShell * m_pEditShell
Definition: autofmt.cxx:92
const int cnPosEmDash
Definition: autofmt.cxx:74
void BuildHeadLine(sal_uInt16 nLvl)
Definition: autofmt.cxx:1881
SwNodeIndex m_aEndNdIdx
Definition: autofmt.cxx:90
#define STR_AUTOFMTREDL_CPTL_STT_SENT
Definition: comcore.hxx:26
void SetAutoFormatRedlineComment(const OUString *pText, sal_uInt16 nSeqNo=0)
Set comment-text for Redline.
std::pair< SwTextNode *, sal_Int32 > MapViewToModel(TextFrameIndex nIndex) const
map position in potentially merged text frame to SwPosition
Definition: txtfrm.cxx:1223
show all deletes
#define STR_AUTOFMTREDL_SET_TMPL_INDENT
Definition: comcore.hxx:38
const SwPosition * Start() const
Definition: pam.hxx:212
Text body first line indent.
Definition: poolfmt.hxx:251
SwPaM m_aDelPam
Definition: autofmt.cxx:88
static SvxSwAutoFormatFlags * s_pAutoFormatFlags
Definition: editsh.hxx:140
SwTextFrameInfo & SetFrame(const SwTextFrame *pNew)
Definition: frminf.hxx:65
void BuildText()
Definition: autofmt.cxx:1433
bool DeleteJoinCurNextPara(SwTextFrame const *pNextFrame, bool bIgnoreLeadingBlanks=false)
Definition: autofmt.cxx:1210
virtual const SwRangeRedline * GetRedline(const SwPosition &rPos, SwRedlineTable::size_type *pFndPos) const =0
void DeleteLeadingTrailingBlanks(bool bStart=true, bool bEnd=true)
delete in the node start and/or end
Definition: autofmt.cxx:1085
SwPaM * GetPrev()
Definition: pam.hxx:268
#define STR_AUTOFMTREDL_SET_TMPL_HEADLINE
Definition: comcore.hxx:41
ignore Redlines
const sal_Unicode cStarSymbolEnDash
Definition: autofmt.cxx:76
#define STR_AUTOFMTREDL_DETECT_URL
Definition: comcore.hxx:33
#define STR_AUTOFMTREDL_SET_NUMBER_BULLET
Definition: comcore.hxx:42
virtual bool TransliterateRTLWord(sal_Int32 &rSttPos, sal_Int32 nEndPos) override
Definition: acorrect.cxx:500
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
void SetAttrListLevel(int nLevel)
Sets the list level of this text node.
Definition: ndtxt.cxx:4052
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:335
constexpr TypedWhichId< SvxBrushItem > RES_BACKGROUND(105)
SvxNumberFormat::SvxNumPositionAndSpaceMode GetDefaultPositionAndSpaceMode()
Definition: number.cxx:1486
bool IsDefBulletFontUserDefined()
determine if default bullet font is user defined
Definition: number.cxx:1315
static SvxSwAutoFormatFlags * GetAutoFormatFlags()
Definition: autofmt.cxx:2804
static bool HasBreakAttr(const SwTextFrame &)
Definition: autofmt.cxx:1053
SwTextFrame * m_pCurTextFrame
Definition: autofmt.cxx:95
unsigned char sal_uInt8
const std::vector< OUString > & GetAutoFormatNameLst() const
Definition: shellres.hxx:87
#define STR_AUTOFMTREDL_UNDER
Definition: comcore.hxx:30
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:254
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:59
#define STR_AUTOFMTREDL_TRANSLITERATE_RTL
Definition: comcore.hxx:45
#define STR_AUTOFMTREDL_ORDINAL
Definition: comcore.hxx:35
virtual void SetRedlineFlags(RedlineFlags eMode)=0
Set a new redline mode.
sal_Int32 GetIndex() const
Definition: index.hxx:91
void SetProgressState(tools::Long nPosition, SwDocShell const *pDocShell)
Definition: mainwn.cxx:82
const sal_uInt16 lNumberIndent
Definition: swtypes.hxx:105
SwNodes & GetNodes()
Definition: doc.hxx:403
const SwPosition * End() const
Definition: pam.hxx:217
static bool IsEmptyLine(const SwTextFrame &rFrame)
Definition: autofmt.cxx:137
virtual bool ChgAutoCorrWord(sal_Int32 &rSttPos, sal_Int32 nEndPos, SvxAutoCorrect &rACorrect, OUString *pPara) override
Definition: acorrect.cxx:365
SvxSwAutoFormatFlags m_aFlags
Definition: autofmt.cxx:87
void * p
#define STR_AUTOFMTREDL_SET_TMPL_NEG_INDENT
Definition: comcore.hxx:39
constexpr TypedWhichId< SvxLRSpaceItem > RES_LR_SPACE(91)
void BuildNegIndent(SwTwips nSpaces)
Definition: autofmt.cxx:1797
constexpr TypedWhichId< SvxBoxItem > RES_BOX(106)
static const sal_Unicode * StrChr(const sal_Unicode *pSrc, sal_Unicode c)
Definition: autofmt.cxx:222
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:722
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:58
static sal_Int32 GetTrailingBlanks(const OUString &rStr)
Definition: autofmt.cxx:720
const SwTextFrame * GetFrame() const
Definition: frminf.hxx:64
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:352
void GetSpaces(std::vector< std::pair< TextFrameIndex, TextFrameIndex >> &, bool bWithLineBreak) const
Definition: frminf.cxx:156
#define DEF_LINE_WIDTH_2
void GotoPrevLayoutTextFrame(SwNodeIndex &rIndex, SwRootFrame const *const pLayout)
Definition: docnum.cxx:1446
SwTwips GetCharPos(TextFrameIndex nChar, bool bCenter=true) const
Definition: frminf.cxx:109
SwTextNode const * pLastNode
mainly for sanity checks
Definition: txtfrm.hxx:959
static OUString DelLeadingBlanks(const OUString &rStr)
Definition: autofmt.cxx:687
bool m_bMoreLines
Definition: autofmt.cxx:116
#define STR_AUTOFMTREDL_END
Definition: comcore.hxx:47
bool IsFirstCharCapital(const SwTextFrame &rNd) const
Definition: autofmt.cxx:731
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
bool IsEnumericChar(const SwTextFrame &) const
Definition: autofmt.cxx:386
SwAutoFormat(SwEditShell *pEdShell, SvxSwAutoFormatFlags const &rFlags, SwNodeIndex const *pSttNd=nullptr, SwNodeIndex const *pEndNd=nullptr)
Definition: autofmt.cxx:2237
bool FnChgWeightUnderl(SvxAutoCorrDoc &, const OUString &, sal_Int32 nEndPos)
bool IsTableNode() const
Definition: node.hxx:648
static bool IsSentenceAtEnd(const SwTextFrame &rTextFrame)
is a dot at the end ??
Definition: autofmt.cxx:1072
Text body hanging indent.
Definition: poolfmt.hxx:252
#define DEF_LINE_WIDTH_0
SwSectionNode * GetSectionNode()
Definition: node.hxx:615
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:475
bool Pop(PopMode)
delete cursor
Definition: crsrsh.cxx:2258
ACFlags GetFlags() const
bool DoUnderline()
Definition: autofmt.cxx:525
void BuildIndent()
Definition: autofmt.cxx:1352
OUString SetNumRule(const SwPaM &, const SwNumRule &, bool bCreateNewList, SwRootFrame const *pLayout=nullptr, const OUString &sContinuedListId=OUString(), bool bSetItem=true, const bool bResetIndentAttrs=false)
Accept changes of outline styles for OutlineRule.
Definition: docnum.cxx:854
constexpr TypedWhichId< SwParaConnectBorderItem > RES_PARATR_CONNECT_BORDER(78)
bool IsFastFullLine(const SwTextFrame &) const
Definition: autofmt.cxx:375
void StartAllAction()
For all views of this document.
Definition: edws.cxx:86
static void SetAutoFormatFlags(SvxSwAutoFormatFlags const *)
Definition: autofmt.cxx:2812
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2073
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:205
const int cnPosEnDash
Definition: autofmt.cxx:74
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
const SwTable * InsertTable(const SwInsertTableOptions &rInsTableOpts, const SwPosition &rPos, sal_uInt16 nRows, sal_uInt16 nCols, sal_Int16 eAdjust, const SwTableAutoFormat *pTAFormat=nullptr, const std::vector< sal_uInt16 > *pColArr=nullptr, bool bCalledFromShell=false, bool bNewModel=true)
Insert new table at position.
Definition: ndtbl.cxx:336
SwTextFrame * GetFrame(const SwTextNode &rTextNd) const
get the FORMATTED TextFrame
Definition: autofmt.cxx:229
CharClass & GetAppCharClass()
Definition: init.cxx:708
bool IsTextNode() const
Definition: node.hxx:644
SwPosition MapViewToModelPos(TextFrameIndex nIndex) const
Definition: txtfrm.cxx:1238
const sal_uInt16 cnNumBullColls
Definition: autofmt.cxx:83
const sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:61
constexpr TypedWhichId< SvxAdjustItem > RES_PARATR_ADJUST(64)
SwRootFrame * getRootFrame()
Definition: frame.hxx:659
SwTextNode * m_pCurTextNd
Definition: autofmt.cxx:94
constexpr TypedWhichId< SvxShadowItem > RES_SHADOW(107)
rtl_TextEncoding GetCharSet() const
sal_uInt16 nPos
SwTextFormatColl & GetNextTextFormatColl() const
Definition: fmtcol.hxx:97
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1315
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:844
static bool IsSpace(const sal_Unicode c)
Definition: autofmt.cxx:128
bool DoTable()
Definition: autofmt.cxx:607
void SetAutoFormatRedline(bool bFlag)
Definition: doc.hxx:1443
#define STR_AUTOFMTREDL_DASH
Definition: comcore.hxx:34
void SetLine(const editeng::SvxBorderLine *pNew, SvxBoxItemLine nLine)
Base class of the Writer document model elements.
Definition: node.hxx:79
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:838
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo