LibreOffice Module vcl (master)  1
textdoc.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 <memory>
21 #include "textdoc.hxx"
22 #include <osl/diagnose.h>
23 #include <sal/log.hxx>
24 
25 // compare function called by QuickSort
26 static bool CompareStart( const std::unique_ptr<TextCharAttrib>& pFirst, const std::unique_ptr<TextCharAttrib>& pSecond )
27 {
28  return pFirst->GetStart() < pSecond->GetStart();
29 }
30 
31 TextCharAttrib::TextCharAttrib( const TextAttrib& rAttr, sal_Int32 nStart, sal_Int32 nEnd )
32  : mpAttr(rAttr.Clone())
33  , mnStart(nStart)
34  , mnEnd(nEnd)
35 {
36 }
37 
39  : mpAttr(rTextCharAttrib.mpAttr->Clone())
40  , mnStart(rTextCharAttrib.mnStart)
41  , mnEnd(rTextCharAttrib.mnEnd)
42 {
43 }
44 
46  : mbHasEmptyAttribs(false)
47 {
48 }
49 
51 {
52  // PTRARR_DEL
53 }
54 
56 {
57  maAttribs.clear();
58 }
59 
60 void TextCharAttribList::InsertAttrib( std::unique_ptr<TextCharAttrib> pAttrib )
61 {
62  if ( pAttrib->IsEmpty() )
63  mbHasEmptyAttribs = true;
64 
65  const sal_Int32 nStart = pAttrib->GetStart(); // maybe better for Comp.Opt.
66  bool bInserted = false;
67  auto it = std::find_if(maAttribs.begin(), maAttribs.end(),
68  [nStart](std::unique_ptr<TextCharAttrib>& rAttrib) { return rAttrib->GetStart() > nStart; });
69  if (it != maAttribs.end())
70  {
71  maAttribs.insert( it, std::move(pAttrib) );
72  bInserted = true;
73  }
74  if ( !bInserted )
75  maAttribs.push_back( std::move(pAttrib) );
76 }
77 
79 {
80  std::sort( maAttribs.begin(), maAttribs.end(), CompareStart );
81 }
82 
83 TextCharAttrib* TextCharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos )
84 {
85  for (std::vector<std::unique_ptr<TextCharAttrib> >::reverse_iterator it = maAttribs.rbegin(); it != maAttribs.rend(); ++it)
86  {
87  if ( (*it)->GetEnd() < nPos )
88  return nullptr;
89 
90  if ( ( (*it)->Which() == nWhich ) && (*it)->IsIn(nPos) )
91  return it->get();
92  }
93  return nullptr;
94 }
95 
96 bool TextCharAttribList::HasBoundingAttrib( sal_Int32 nBound )
97 {
98  for (std::vector<std::unique_ptr<TextCharAttrib> >::reverse_iterator it = maAttribs.rbegin(); it != maAttribs.rend(); ++it)
99  {
100  if ( (*it)->GetEnd() < nBound )
101  return false;
102 
103  if ( ( (*it)->GetStart() == nBound ) || ( (*it)->GetEnd() == nBound ) )
104  return true;
105  }
106  return false;
107 }
108 
109 TextCharAttrib* TextCharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_Int32 nPos )
110 {
111  if ( !mbHasEmptyAttribs )
112  return nullptr;
113 
114  for (auto const& attrib : maAttribs)
115  {
116  if ( attrib->GetStart() > nPos )
117  return nullptr;
118 
119  if ( ( attrib->GetStart() == nPos ) && ( attrib->GetEnd() == nPos ) && ( attrib->Which() == nWhich ) )
120  return attrib.get();
121  }
122  return nullptr;
123 }
124 
126 {
127  maAttribs.erase(
128  std::remove_if( maAttribs.begin(), maAttribs.end(),
129  [] (const std::unique_ptr<TextCharAttrib>& rAttrib) { return rAttrib->IsEmpty(); } ),
130  maAttribs.end() );
131  mbHasEmptyAttribs = false;
132 }
133 
134 TextNode::TextNode( const OUString& rText ) :
135  maText( rText )
136 {
137 }
138 
139 void TextNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew )
140 {
141  if ( !nNew )
142  return;
143 
144  bool bResort = false;
145  sal_uInt16 nAttribs = maCharAttribs.Count();
146  for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
147  {
148  TextCharAttrib& rAttrib = maCharAttribs.GetAttrib( nAttr );
149  if ( rAttrib.GetEnd() >= nIndex )
150  {
151  // move all attributes that are behind the cursor
152  if ( rAttrib.GetStart() > nIndex )
153  {
154  rAttrib.MoveForward( nNew );
155  }
156  // 0: expand empty attribute, if at cursor
157  else if ( rAttrib.IsEmpty() )
158  {
159  // Do not check the index; empty one may only be here.
160  // If checking later anyway, special case:
161  // Start == 0; AbsLen == 1, nNew = 1 => Expand due to new paragraph!
162  // Start <= nIndex, End >= nIndex => Start=End=nIndex!
163  rAttrib.Expand( nNew );
164  }
165  // 1: attribute starts before and reaches up to index
166  else if ( rAttrib.GetEnd() == nIndex ) // start must be before
167  {
168  // Only expand if no feature and not in Exclude list!
169  // Otherwise e.g. an UL would go until the new ULDB, thus expand both.
170  if ( !maCharAttribs.FindEmptyAttrib( rAttrib.Which(), nIndex ) )
171  {
172  rAttrib.Expand( nNew );
173  }
174  else
175  bResort = true;
176  }
177  // 2: attribute starts before and reaches past the index
178  else if ( ( rAttrib.GetStart() < nIndex ) && ( rAttrib.GetEnd() > nIndex ) )
179  {
180  rAttrib.Expand( nNew );
181  }
182  // 3: attribute starts at Index
183  else if ( rAttrib.GetStart() == nIndex )
184  {
185  if ( nIndex == 0 )
186  {
187  rAttrib.Expand( nNew );
188  }
189  else
190  rAttrib.MoveForward( nNew );
191  }
192  }
193 
194  SAL_WARN_IF( rAttrib.GetStart() > rAttrib.GetEnd(), "vcl", "Expand: attribute twisted!" );
195  SAL_WARN_IF( ( rAttrib.GetEnd() > maText.getLength() ), "vcl", "Expand: attribute greater than paragraph!" );
196  SAL_WARN_IF( rAttrib.IsEmpty(), "vcl", "Empty attribute after ExpandAttribs?" );
197  }
198 
199  if ( bResort )
201 }
202 
203 void TextNode::CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDeleted )
204 {
205  if ( !nDeleted )
206  return;
207 
208  bool bResort = false;
209  const sal_Int32 nEndChanges = nIndex+nDeleted;
210 
211  for ( sal_uInt16 nAttr = 0; nAttr < maCharAttribs.Count(); nAttr++ )
212  {
213  TextCharAttrib& rAttrib = maCharAttribs.GetAttrib( nAttr );
214  bool bDelAttr = false;
215  if ( rAttrib.GetEnd() >= nIndex )
216  {
217  // move all attributes that are behind the cursor
218  if ( rAttrib.GetStart() >= nEndChanges )
219  {
220  rAttrib.MoveBackward( nDeleted );
221  }
222  // 1. delete inner attributes
223  else if ( ( rAttrib.GetStart() >= nIndex ) && ( rAttrib.GetEnd() <= nEndChanges ) )
224  {
225  // special case: attribute covers the region exactly
226  // => keep as an empty attribute
227  if ( ( rAttrib.GetStart() == nIndex ) && ( rAttrib.GetEnd() == nEndChanges ) )
228  rAttrib.SetEnd(nIndex); // empty
229  else
230  bDelAttr = true;
231  }
232  // 2. attribute starts before, ends inside or after
233  else if ( ( rAttrib.GetStart() <= nIndex ) && ( rAttrib.GetEnd() > nIndex ) )
234  {
235  if ( rAttrib.GetEnd() <= nEndChanges ) // ends inside
236  rAttrib.SetEnd(nIndex);
237  else
238  rAttrib.Collaps( nDeleted ); // ends after
239  }
240  // 3. attribute starts inside, ends after
241  else if ( ( rAttrib.GetStart() >= nIndex ) && ( rAttrib.GetEnd() > nEndChanges ) )
242  {
243  // features are not allowed to expand!
244  rAttrib.SetStart(nEndChanges);
245  rAttrib.MoveBackward( nDeleted );
246  }
247  }
248 
249  SAL_WARN_IF( rAttrib.GetStart() > rAttrib.GetEnd(), "vcl", "Collaps: attribute twisted!" );
250  SAL_WARN_IF( ( rAttrib.GetEnd() > maText.getLength()) && !bDelAttr, "vcl", "Collaps: attribute greater than paragraph!" );
251  if ( bDelAttr /* || rAttrib.IsEmpty() */ )
252  {
253  bResort = true;
254  maCharAttribs.RemoveAttrib( nAttr );
255  nAttr--;
256  }
257  else if ( rAttrib.IsEmpty() )
259  }
260 
261  if ( bResort )
263 }
264 
265 void TextNode::InsertText( sal_Int32 nPos, const OUString& rText )
266 {
267  maText = maText.replaceAt( nPos, 0, rText );
268  ExpandAttribs( nPos, rText.getLength() );
269 }
270 
271 void TextNode::InsertText( sal_Int32 nPos, sal_Unicode c )
272 {
273  maText = maText.replaceAt( nPos, 0, OUString(c) );
274  ExpandAttribs( nPos, 1 );
275 }
276 
277 void TextNode::RemoveText( sal_Int32 nPos, sal_Int32 nChars )
278 {
279  maText = maText.replaceAt( nPos, nChars, "" );
280  CollapseAttribs( nPos, nChars );
281 }
282 
283 std::unique_ptr<TextNode> TextNode::Split( sal_Int32 nPos )
284 {
285  OUString aNewText;
286  if ( nPos < maText.getLength() )
287  {
288  aNewText = maText.copy( nPos );
289  maText = maText.copy(0, nPos);
290  }
291  std::unique_ptr<TextNode> pNew(new TextNode( aNewText ));
292 
293  for ( sal_uInt16 nAttr = 0; nAttr < maCharAttribs.Count(); nAttr++ )
294  {
295  TextCharAttrib& rAttrib = maCharAttribs.GetAttrib( nAttr );
296  if ( rAttrib.GetEnd() < nPos )
297  {
298  // no change
299  ;
300  }
301  else if ( rAttrib.GetEnd() == nPos )
302  {
303  // must be copied as an empty attribute
304  // !FindAttrib only sensible if traversing backwards through the list!
305  if ( !pNew->maCharAttribs.FindAttrib( rAttrib.Which(), 0 ) )
306  {
307  std::unique_ptr<TextCharAttrib> pNewAttrib(new TextCharAttrib( rAttrib ));
308  pNewAttrib->SetStart(0);
309  pNewAttrib->SetEnd(0);
310  pNew->maCharAttribs.InsertAttrib( std::move(pNewAttrib) );
311  }
312  }
313  else if ( rAttrib.IsInside( nPos ) || ( !nPos && !rAttrib.GetStart() ) )
314  {
315  // If cutting at the very beginning, the attribute has to be
316  // copied and changed
317  std::unique_ptr<TextCharAttrib> pNewAttrib(new TextCharAttrib( rAttrib ));
318  pNewAttrib->SetStart(0);
319  pNewAttrib->SetEnd(rAttrib.GetEnd()-nPos);
320  pNew->maCharAttribs.InsertAttrib( std::move(pNewAttrib) );
321  // trim
322  rAttrib.SetEnd(nPos);
323  }
324  else
325  {
326  SAL_WARN_IF( rAttrib.GetStart() < nPos, "vcl", "Start < nPos!" );
327  SAL_WARN_IF( rAttrib.GetEnd() < nPos, "vcl", "End < nPos!" );
328  // move all into the new node (this)
329  pNew->maCharAttribs.InsertAttrib(maCharAttribs.RemoveAttrib(nAttr));
330  rAttrib.SetStart( rAttrib.GetStart() - nPos );
331  rAttrib.SetEnd( rAttrib.GetEnd() - nPos );
332  nAttr--;
333  }
334  }
335  return pNew;
336 }
337 
338 void TextNode::Append( const TextNode& rNode )
339 {
340  sal_Int32 nOldLen = maText.getLength();
341 
342  maText += rNode.GetText();
343 
344  const sal_uInt16 nAttribs = rNode.GetCharAttribs().Count();
345  for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
346  {
347  const TextCharAttrib& rAttrib = rNode.GetCharAttrib( nAttr );
348  bool bMelted = false;
349  if ( rAttrib.GetStart() == 0 )
350  {
351  // potentially merge attributes
352  sal_uInt16 nTmpAttribs = maCharAttribs.Count();
353  for ( sal_uInt16 nTmpAttr = 0; nTmpAttr < nTmpAttribs; nTmpAttr++ )
354  {
355  TextCharAttrib& rTmpAttrib = maCharAttribs.GetAttrib( nTmpAttr );
356 
357  if ( rTmpAttrib.GetEnd() == nOldLen )
358  {
359  if ( ( rTmpAttrib.Which() == rAttrib.Which() ) &&
360  ( rTmpAttrib.GetAttr() == rAttrib.GetAttr() ) )
361  {
362  rTmpAttrib.SetEnd( rTmpAttrib.GetEnd() + rAttrib.GetLen() );
363  bMelted = true;
364  break; // there can be only one of this type at this position
365  }
366  }
367  }
368  }
369 
370  if ( !bMelted )
371  {
372  std::unique_ptr<TextCharAttrib> pNewAttrib(new TextCharAttrib( rAttrib ));
373  pNewAttrib->SetStart( pNewAttrib->GetStart() + nOldLen );
374  pNewAttrib->SetEnd( pNewAttrib->GetEnd() + nOldLen );
375  maCharAttribs.InsertAttrib( std::move(pNewAttrib) );
376  }
377  }
378 }
379 
381  : mnLeftMargin(0)
382 {
383 };
384 
386 {
388 }
389 
391 {
393 }
394 
396 {
397  maTextNodes.clear();
398 }
399 
400 OUString TextDoc::GetText( const sal_Unicode* pSep ) const
401 {
402  sal_uInt32 nNodes = static_cast<sal_uInt32>(maTextNodes.size());
403 
404  OUStringBuffer aASCIIText;
405  const sal_uInt32 nLastNode = nNodes-1;
406  for ( sal_uInt32 nNode = 0; nNode < nNodes; ++nNode )
407  {
408  TextNode* pNode = maTextNodes[ nNode ].get();
409  aASCIIText.append(pNode->GetText());
410  if ( pSep && ( nNode != nLastNode ) )
411  aASCIIText.append(pSep);
412  }
413 
414  return aASCIIText.makeStringAndClear();
415 }
416 
417 OUString TextDoc::GetText( sal_uInt32 nPara ) const
418 {
419  TextNode* pNode = ( nPara < maTextNodes.size() ) ? maTextNodes[ nPara ].get() : nullptr;
420  if ( pNode )
421  return pNode->GetText();
422 
423  return OUString();
424 }
425 
426 sal_Int32 TextDoc::GetTextLen( const sal_Unicode* pSep, const TextSelection* pSel ) const
427 {
428  sal_Int32 nLen = 0;
429  sal_uInt32 nNodes = static_cast<sal_uInt32>(maTextNodes.size());
430  if ( nNodes )
431  {
432  sal_uInt32 nStartNode = 0;
433  sal_uInt32 nEndNode = nNodes-1;
434  if ( pSel )
435  {
436  nStartNode = pSel->GetStart().GetPara();
437  nEndNode = pSel->GetEnd().GetPara();
438  }
439 
440  for ( sal_uInt32 nNode = nStartNode; nNode <= nEndNode; ++nNode )
441  {
442  TextNode* pNode = maTextNodes[ nNode ].get();
443 
444  sal_Int32 nS = 0;
445  sal_Int32 nE = pNode->GetText().getLength();
446  if ( pSel && ( nNode == pSel->GetStart().GetPara() ) )
447  nS = pSel->GetStart().GetIndex();
448  if ( pSel && ( nNode == pSel->GetEnd().GetPara() ) )
449  nE = pSel->GetEnd().GetIndex();
450 
451  nLen += ( nE - nS );
452  }
453 
454  if ( pSep )
455  nLen += (nEndNode-nStartNode) * rtl_ustr_getLength(pSep);
456  }
457 
458  return nLen;
459 }
460 
462 {
463  SAL_WARN_IF( c == 0x0A, "vcl", "TextDoc::InsertText: Line separator in paragraph not allowed!" );
464  SAL_WARN_IF( c == 0x0D, "vcl", "TextDoc::InsertText: Line separator in paragraph not allowed!" );
465 
466  TextNode* pNode = maTextNodes[ rPaM.GetPara() ].get();
467  pNode->InsertText( rPaM.GetIndex(), c );
468 
469  TextPaM aPaM( rPaM.GetPara(), rPaM.GetIndex()+1 );
470  return aPaM;
471 }
472 
473 TextPaM TextDoc::InsertText( const TextPaM& rPaM, const OUString& rStr )
474 {
475  SAL_WARN_IF( rStr.indexOf( 0x0A ) != -1, "vcl", "TextDoc::InsertText: Line separator in paragraph not allowed!" );
476  SAL_WARN_IF( rStr.indexOf( 0x0D ) != -1, "vcl", "TextDoc::InsertText: Line separator in paragraph not allowed!" );
477 
478  TextNode* pNode = maTextNodes[ rPaM.GetPara() ].get();
479  pNode->InsertText( rPaM.GetIndex(), rStr );
480 
481  TextPaM aPaM( rPaM.GetPara(), rPaM.GetIndex()+rStr.getLength() );
482  return aPaM;
483 }
484 
486 {
487  TextNode* pNode = maTextNodes[ rPaM.GetPara() ].get();
488  std::unique_ptr<TextNode> pNew = pNode->Split( rPaM.GetIndex() );
489 
490  SAL_WARN_IF( maTextNodes.size()>=SAL_MAX_UINT32, "vcl", "InsertParaBreak: more than 4Gi paragraphs!" );
491  maTextNodes.insert( maTextNodes.begin() + rPaM.GetPara() + 1, std::move(pNew) );
492 
493  TextPaM aPaM( rPaM.GetPara()+1, 0 );
494  return aPaM;
495 }
496 
498 {
499  sal_Int32 nPrevLen = pLeft->GetText().getLength();
500  pLeft->Append( *pRight );
501 
502  // the paragraph on the right vanishes
503  maTextNodes.erase( std::find_if( maTextNodes.begin(), maTextNodes.end(),
504  [&] (std::unique_ptr<TextNode> const & p) { return p.get() == pRight; } ) );
505 
506  sal_uLong nLeft = ::std::find_if( maTextNodes.begin(), maTextNodes.end(),
507  [&] (std::unique_ptr<TextNode> const & p) { return p.get() == pLeft; } )
508  - maTextNodes.begin();
509  TextPaM aPaM( nLeft, nPrevLen );
510  return aPaM;
511 }
512 
513 void TextDoc::RemoveChars( const TextPaM& rPaM, sal_Int32 nChars )
514 {
515  TextNode* pNode = maTextNodes[ rPaM.GetPara() ].get();
516  pNode->RemoveText( rPaM.GetIndex(), nChars );
517 }
518 
519 bool TextDoc::IsValidPaM( const TextPaM& rPaM )
520 {
521  if ( rPaM.GetPara() >= maTextNodes.size() )
522  {
523  OSL_FAIL( "PaM: Para out of range" );
524  return false;
525  }
526  TextNode * pNode = maTextNodes[ rPaM.GetPara() ].get();
527  if ( rPaM.GetIndex() > pNode->GetText().getLength() )
528  {
529  OSL_FAIL( "PaM: Index out of range" );
530  return false;
531  }
532  return true;
533 }
534 
535 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 GetLen() const
Definition: txtattr.hxx:140
size_t mnEnd
~TextDoc()
Definition: textdoc.cxx:385
OUString GetText(const sal_Unicode *pSep) const
Definition: textdoc.cxx:400
sal_uIntPtr sal_uLong
TextDoc()
Definition: textdoc.cxx:380
void DestroyTextNodes()
Definition: textdoc.cxx:395
const TextPaM & GetEnd() const
Definition: textdata.hxx:94
void InsertText(sal_Int32 nPos, const OUString &rText)
Definition: textdoc.cxx:265
void DeleteEmptyAttribs()
Definition: textdoc.cxx:125
sal_Int32 GetStart() const
Definition: txtattr.hxx:120
std::unique_ptr< TextCharAttrib > RemoveAttrib(sal_uInt16 n)
Definition: textdoc.hxx:47
const TextCharAttrib & GetAttrib(sal_uInt16 n) const
Definition: textdoc.hxx:45
void Collaps(sal_Int32 nDiff)
Definition: txtattr.hxx:166
#define SAL_MAX_UINT32
sal_Int32 GetTextLen(const sal_Unicode *pSep, const TextSelection *pSel=nullptr) const
Definition: textdoc.cxx:426
sal_uInt16 sal_Unicode
TextPaM InsertParaBreak(const TextPaM &rPaM)
Definition: textdoc.cxx:485
const TextCharAttrib & GetCharAttrib(sal_uInt16 nPos) const
Definition: textdoc.hxx:82
sal_uInt16 Count() const
Definition: textdoc.hxx:43
bool IsEmpty() const
Definition: txtattr.hxx:182
bool IsInside(sal_Int32 nIndex)
Definition: txtattr.hxx:177
Reference< XAnimationNode > Clone(const Reference< XAnimationNode > &xSourceNode, const SdPage *pSource, const SdPage *pTarget)
void SetEnd(sal_Int32 n)
Definition: txtattr.hxx:124
static bool CompareStart(const std::unique_ptr< TextCharAttrib > &pFirst, const std::unique_ptr< TextCharAttrib > &pSecond)
Definition: textdoc.cxx:26
const TextPaM & GetStart() const
Definition: textdata.hxx:91
sal_uInt16 Which() const
Definition: txtattr.hxx:118
bool & HasEmptyAttribs()
Definition: textdoc.hxx:59
void MoveBackward(sal_Int32 nDiff)
Definition: txtattr.hxx:153
void ExpandAttribs(sal_Int32 nIndex, sal_Int32 nNewChars)
Definition: textdoc.cxx:139
bool mbHasEmptyAttribs
Definition: textdoc.hxx:36
const TextAttrib & GetAttr() const
Definition: txtattr.hxx:116
TextCharAttrib * FindEmptyAttrib(sal_uInt16 nWhich, sal_Int32 nPos)
Definition: textdoc.cxx:109
void Clear()
Definition: textdoc.cxx:390
void RemoveChars(const TextPaM &rPaM, sal_Int32 nChars)
Definition: textdoc.cxx:513
void Expand(sal_Int32 nDiff)
Definition: txtattr.hxx:160
std::vector< std::unique_ptr< TextCharAttrib > > maAttribs
Definition: textdoc.hxx:35
size_t mnStart
const TextCharAttribList & GetCharAttribs() const
Definition: textdoc.hxx:83
void Append(const TextNode &rNode)
Definition: textdoc.cxx:338
bool IsValidPaM(const TextPaM &rPaM)
Definition: textdoc.cxx:519
Text maText
void InsertAttrib(std::unique_ptr< TextCharAttrib > pAttrib)
Definition: textdoc.cxx:60
#define SAL_WARN_IF(condition, area, stream)
TextNode(const OUString &rText)
Definition: textdoc.cxx:134
sal_Int32 GetEnd() const
Definition: txtattr.hxx:123
TextCharAttrib(const TextAttrib &rAttr, sal_Int32 nStart, sal_Int32 nEnd)
Definition: textdoc.cxx:31
sal_Int32 GetIndex() const
Definition: textdata.hxx:49
bool HasBoundingAttrib(sal_Int32 nBound)
Definition: textdoc.cxx:96
OUString maText
Definition: textdoc.hxx:68
void ResortAttribs()
Definition: textdoc.cxx:78
std::unique_ptr< TextNode > Split(sal_Int32 nPos)
Definition: textdoc.cxx:283
TextPaM InsertText(const TextPaM &rPaM, sal_Unicode c)
Definition: textdoc.cxx:461
void RemoveText(sal_Int32 nPos, sal_Int32 nChars)
Definition: textdoc.cxx:277
const OUString & GetText() const
Definition: textdoc.hxx:80
TextPaM ConnectParagraphs(TextNode *pLeft, const TextNode *pRight)
Definition: textdoc.cxx:497
TextCharAttrib * FindAttrib(sal_uInt16 nWhich, sal_Int32 nPos)
Definition: textdoc.cxx:83
TextCharAttribList maCharAttribs
Definition: textdoc.hxx:69
sal_uInt32 GetPara() const
Definition: textdata.hxx:46
void CollapseAttribs(sal_Int32 nIndex, sal_Int32 nDelChars)
Definition: textdoc.cxx:203
void MoveForward(sal_Int32 nDiff)
Definition: txtattr.hxx:146
std::vector< std::unique_ptr< TextNode > > maTextNodes
Definition: textdoc.hxx:96
void SetStart(sal_Int32 n)
Definition: txtattr.hxx:121