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