LCOV - code coverage report
Current view: top level - vcl/source/edit - textdoc.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 38 308 12.3 %
Date: 2012-08-25 Functions: 10 36 27.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 8 298 2.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <textdoc.hxx>
      30                 :            : 
      31                 :            : #include <stdlib.h>
      32                 :            : 
      33                 :            : 
      34                 :            : 
      35                 :            : // Vergleichmethode wird von QuickSort gerufen...
      36                 :            : 
      37                 :          0 : static bool CompareStart( const TextCharAttrib* pFirst, const TextCharAttrib* pSecond )
      38                 :            : {
      39                 :          0 :     return pFirst->GetStart() < pSecond->GetStart();
      40                 :            : }
      41                 :            : 
      42                 :            : // -------------------------------------------------------------------------
      43                 :            : // (+) class TextCharAttrib
      44                 :            : // -------------------------------------------------------------------------
      45                 :          0 : TextCharAttrib::TextCharAttrib( const TextAttrib& rAttr, sal_uInt16 nStart, sal_uInt16 nEnd )
      46                 :            : {
      47                 :          0 :     mpAttr = rAttr.Clone();
      48                 :            :     mnStart = nStart,
      49                 :          0 :     mnEnd = nEnd;
      50                 :          0 : }
      51                 :            : 
      52                 :          0 : TextCharAttrib::TextCharAttrib( const TextCharAttrib& rTextCharAttrib )
      53                 :            : {
      54                 :          0 :     mpAttr = rTextCharAttrib.GetAttr().Clone();
      55                 :          0 :     mnStart = rTextCharAttrib.mnStart;
      56                 :          0 :     mnEnd = rTextCharAttrib.mnEnd;
      57                 :          0 : }
      58                 :            : 
      59                 :          0 : TextCharAttrib::~TextCharAttrib()
      60                 :            : {
      61         [ #  # ]:          0 :     delete mpAttr;
      62                 :          0 : }
      63                 :            : 
      64                 :            : // -------------------------------------------------------------------------
      65                 :            : // (+) class TextCharAttribList
      66                 :            : // -------------------------------------------------------------------------
      67                 :            : 
      68                 :        218 : TextCharAttribList::TextCharAttribList()
      69                 :            : {
      70                 :        218 :     mbHasEmptyAttribs = sal_False;
      71                 :        218 : }
      72                 :            : 
      73                 :        218 : TextCharAttribList::~TextCharAttribList()
      74                 :            : {
      75                 :            :     // PTRARR_DEL
      76                 :        218 : }
      77                 :            : 
      78                 :          0 : void TextCharAttribList::Clear( sal_Bool bDestroyAttribs )
      79                 :            : {
      80         [ #  # ]:          0 :     if ( bDestroyAttribs )
      81 [ #  # ][ #  # ]:          0 :         for(iterator it = begin(); it != end(); ++it)
      82 [ #  # ][ #  # ]:          0 :             delete *it;
      83                 :          0 :     TextCharAttribs::clear();
      84                 :          0 : }
      85                 :            : 
      86                 :            : 
      87                 :          0 : void TextCharAttribList::InsertAttrib( TextCharAttrib* pAttrib )
      88                 :            : {
      89         [ #  # ]:          0 :     if ( pAttrib->IsEmpty() )
      90                 :          0 :         mbHasEmptyAttribs = sal_True;
      91                 :            : 
      92                 :          0 :     const sal_uInt16 nCount = size();
      93                 :          0 :     const sal_uInt16 nStart = pAttrib->GetStart(); // vielleicht besser fuer Comp.Opt.
      94                 :          0 :     sal_Bool bInserted = sal_False;
      95         [ #  # ]:          0 :     for ( sal_uInt16 x = 0; x < nCount; x++ )
      96                 :            :     {
      97                 :          0 :         TextCharAttrib* pCurAttrib = GetAttrib( x );
      98         [ #  # ]:          0 :         if ( pCurAttrib->GetStart() > nStart )
      99                 :            :         {
     100 [ #  # ][ #  # ]:          0 :             insert( begin() + x, pAttrib );
     101                 :          0 :             bInserted = sal_True;
     102                 :          0 :             break;
     103                 :            :         }
     104                 :            :     }
     105         [ #  # ]:          0 :     if ( !bInserted )
     106                 :          0 :         push_back( pAttrib );
     107                 :          0 : }
     108                 :            : 
     109                 :          0 : void TextCharAttribList::ResortAttribs()
     110                 :            : {
     111         [ #  # ]:          0 :     if ( !empty() )
     112                 :          0 :         std::sort( begin(), end(), CompareStart );
     113                 :          0 : }
     114                 :            : 
     115                 :          0 : TextCharAttrib* TextCharAttribList::FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos )
     116                 :            : {
     117                 :            :     // Rueckwaerts, falls eins dort endet, das naechste startet.
     118                 :            :     // => Das startende gilt...
     119                 :            : 
     120         [ #  # ]:          0 :     for ( sal_uInt16 nAttr = size(); nAttr; )
     121                 :            :     {
     122                 :          0 :         TextCharAttrib* pAttr = GetAttrib( --nAttr );
     123                 :            : 
     124         [ #  # ]:          0 :         if ( pAttr->GetEnd() < nPos )
     125                 :          0 :             return 0;
     126                 :            : 
     127 [ #  # ][ #  # ]:          0 :         if ( ( pAttr->Which() == nWhich ) && pAttr->IsIn(nPos) )
                 [ #  # ]
     128                 :          0 :             return pAttr;
     129                 :            :     }
     130                 :          0 :     return NULL;
     131                 :            : }
     132                 :            : 
     133                 :          0 : TextCharAttrib* TextCharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_uInt16 nFromPos, sal_uInt16 nMaxPos ) const
     134                 :            : {
     135                 :            :     DBG_ASSERT( nWhich, "FindNextAttrib: Which?" );
     136                 :          0 :     const sal_uInt16 nAttribs = size();
     137         [ #  # ]:          0 :     for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
     138                 :            :     {
     139                 :          0 :         TextCharAttrib* pAttr = GetAttrib( nAttr );
     140 [ #  # ][ #  #  :          0 :         if ( ( pAttr->GetStart() >= nFromPos ) &&
             #  #  #  # ]
     141                 :          0 :              ( pAttr->GetEnd() <= nMaxPos ) &&
     142                 :          0 :              ( pAttr->Which() == nWhich ) )
     143                 :          0 :             return pAttr;
     144                 :            :     }
     145                 :          0 :     return NULL;
     146                 :            : }
     147                 :            : 
     148                 :          0 : sal_Bool TextCharAttribList::HasAttrib( sal_uInt16 nWhich ) const
     149                 :            : {
     150         [ #  # ]:          0 :     for ( sal_uInt16 nAttr = size(); nAttr; )
     151                 :            :     {
     152                 :          0 :         const TextCharAttrib* pAttr = GetAttrib( --nAttr );
     153         [ #  # ]:          0 :         if ( pAttr->Which() == nWhich )
     154                 :          0 :             return sal_True;
     155                 :            :     }
     156                 :          0 :     return sal_False;
     157                 :            : }
     158                 :            : 
     159                 :          0 : sal_Bool TextCharAttribList::HasBoundingAttrib( sal_uInt16 nBound )
     160                 :            : {
     161                 :            :     // Rueckwaerts, falls eins dort endet, das naechste startet.
     162                 :            :     // => Das startende gilt...
     163         [ #  # ]:          0 :     for ( sal_uInt16 nAttr = size(); nAttr; )
     164                 :            :     {
     165                 :          0 :         TextCharAttrib* pAttr = GetAttrib( --nAttr );
     166                 :            : 
     167         [ #  # ]:          0 :         if ( pAttr->GetEnd() < nBound )
     168                 :          0 :             return sal_False;
     169                 :            : 
     170 [ #  # ][ #  # ]:          0 :         if ( ( pAttr->GetStart() == nBound ) || ( pAttr->GetEnd() == nBound ) )
                 [ #  # ]
     171                 :          0 :             return sal_True;
     172                 :            :     }
     173                 :          0 :     return sal_False;
     174                 :            : }
     175                 :            : 
     176                 :          0 : TextCharAttrib* TextCharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos )
     177                 :            : {
     178         [ #  # ]:          0 :     if ( !mbHasEmptyAttribs )
     179                 :          0 :         return 0;
     180                 :            : 
     181                 :          0 :     const sal_uInt16 nAttribs = size();
     182         [ #  # ]:          0 :     for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
     183                 :            :     {
     184                 :          0 :         TextCharAttrib* pAttr = GetAttrib( nAttr );
     185         [ #  # ]:          0 :         if ( pAttr->GetStart() > nPos )
     186                 :          0 :             return 0;
     187                 :            : 
     188 [ #  # ][ #  # ]:          0 :         if ( ( pAttr->GetStart() == nPos ) && ( pAttr->GetEnd() == nPos ) && ( pAttr->Which() == nWhich ) )
         [ #  # ][ #  # ]
     189                 :          0 :             return pAttr;
     190                 :            :     }
     191                 :          0 :     return 0;
     192                 :            : }
     193                 :            : 
     194                 :          0 : void TextCharAttribList::DeleteEmptyAttribs()
     195                 :            : {
     196         [ #  # ]:          0 :     for ( sal_uInt16 nAttr = 0; nAttr < size(); nAttr++ )
     197                 :            :     {
     198                 :          0 :         TextCharAttrib* pAttr = GetAttrib( nAttr );
     199         [ #  # ]:          0 :         if ( pAttr->IsEmpty() )
     200                 :            :         {
     201 [ #  # ][ #  # ]:          0 :             erase( begin() + nAttr );
     202         [ #  # ]:          0 :             delete pAttr;
     203                 :          0 :             nAttr--;
     204                 :            :         }
     205                 :            :     }
     206                 :          0 :     mbHasEmptyAttribs = sal_False;
     207                 :          0 : }
     208                 :            : 
     209                 :            : // -------------------------------------------------------------------------
     210                 :            : // (+) class TextNode
     211                 :            : // -------------------------------------------------------------------------
     212                 :            : 
     213                 :        218 : TextNode::TextNode( const String& rText ) :
     214         [ +  - ]:        218 :     maText( rText )
     215                 :            : {
     216                 :        218 : }
     217                 :            : 
     218                 :         52 : void TextNode::ExpandAttribs( sal_uInt16 nIndex, sal_uInt16 nNew )
     219                 :            : {
     220         [ -  + ]:         52 :     if ( !nNew )
     221                 :         52 :         return;
     222                 :            : 
     223                 :         52 :     sal_Bool bResort = sal_False;
     224                 :         52 :     sal_uInt16 nAttribs = maCharAttribs.Count();
     225         [ -  + ]:         52 :     for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
     226                 :            :     {
     227                 :          0 :         TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr );
     228         [ #  # ]:          0 :         if ( pAttrib->GetEnd() >= nIndex )
     229                 :            :         {
     230                 :            :             // Alle Attribute hinter der Einfuegeposition verschieben...
     231         [ #  # ]:          0 :             if ( pAttrib->GetStart() > nIndex )
     232                 :            :             {
     233                 :          0 :                 pAttrib->MoveForward( nNew );
     234                 :            :             }
     235                 :            :             // 0: Leeres Attribut expandieren, wenn an Einfuegestelle
     236         [ #  # ]:          0 :             else if ( pAttrib->IsEmpty() )
     237                 :            :             {
     238                 :            :                 // Index nicht pruefen, leeres durfte nur dort liegen.
     239                 :            :                 // Wenn spaeter doch Ueberpruefung:
     240                 :            :                 //   Spezialfall: Start == 0; AbsLen == 1, nNew = 1 => Expand, weil durch Absatzumbruch!
     241                 :            :                 // Start <= nIndex, End >= nIndex => Start=End=nIndex!
     242                 :            : //              if ( pAttrib->GetStart() == nIndex )
     243                 :          0 :                     pAttrib->Expand( nNew );
     244                 :            :             }
     245                 :            :             // 1: Attribut startet davor, geht bis Index...
     246         [ #  # ]:          0 :             else if ( pAttrib->GetEnd() == nIndex ) // Start muss davor liegen
     247                 :            :             {
     248                 :            :                 // Nur expandieren, wenn kein Feature,
     249                 :            :                 // und wenn nicht in ExcludeListe!
     250                 :            :                 // Sonst geht z.B. ein UL bis zum neuen ULDB, beide expandieren
     251         [ #  # ]:          0 :                 if ( !maCharAttribs.FindEmptyAttrib( pAttrib->Which(), nIndex ) )
     252                 :            :                 {
     253                 :          0 :                     pAttrib->Expand( nNew );
     254                 :            :                 }
     255                 :            :                 else
     256                 :          0 :                     bResort = sal_True;
     257                 :            :             }
     258                 :            :             // 2: Attribut startet davor, geht hinter Index...
     259 [ #  # ][ #  # ]:          0 :             else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
                 [ #  # ]
     260                 :            :             {
     261                 :          0 :                 pAttrib->Expand( nNew );
     262                 :            :             }
     263                 :            :             // 3: Attribut startet auf Index...
     264         [ #  # ]:          0 :             else if ( pAttrib->GetStart() == nIndex )
     265                 :            :             {
     266         [ #  # ]:          0 :                 if ( nIndex == 0 )
     267                 :            :                 {
     268                 :          0 :                     pAttrib->Expand( nNew );
     269                 :            : //                  bResort = sal_True;     // es gibt ja keine Features mehr...
     270                 :            :                 }
     271                 :            :                 else
     272                 :          0 :                     pAttrib->MoveForward( nNew );
     273                 :            :             }
     274                 :            :         }
     275                 :            : 
     276                 :            :         DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribut verdreht!" );
     277                 :            :         DBG_ASSERT( ( pAttrib->GetEnd() <= maText.Len() ), "Expand: Attrib groesser als Absatz!" );
     278                 :            :         DBG_ASSERT( !pAttrib->IsEmpty(), "Leeres Attribut nach ExpandAttribs?" );
     279                 :            :     }
     280                 :            : 
     281         [ -  + ]:         52 :     if ( bResort )
     282                 :          0 :         maCharAttribs.ResortAttribs();
     283                 :            : }
     284                 :            : 
     285                 :          0 : void TextNode::CollapsAttribs( sal_uInt16 nIndex, sal_uInt16 nDeleted )
     286                 :            : {
     287         [ #  # ]:          0 :     if ( !nDeleted )
     288                 :          0 :         return;
     289                 :            : 
     290                 :          0 :     sal_Bool bResort = sal_False;
     291                 :          0 :     sal_uInt16 nEndChanges = nIndex+nDeleted;
     292                 :            : 
     293         [ #  # ]:          0 :     for ( sal_uInt16 nAttr = 0; nAttr < maCharAttribs.Count(); nAttr++ )
     294                 :            :     {
     295                 :          0 :         TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr );
     296                 :          0 :         sal_Bool bDelAttr = sal_False;
     297         [ #  # ]:          0 :         if ( pAttrib->GetEnd() >= nIndex )
     298                 :            :         {
     299                 :            :             // Alles Attribute hinter der Einfuegeposition verschieben...
     300         [ #  # ]:          0 :             if ( pAttrib->GetStart() >= nEndChanges )
     301                 :            :             {
     302                 :          0 :                 pAttrib->MoveBackward( nDeleted );
     303                 :            :             }
     304                 :            :             // 1. Innenliegende Attribute loeschen...
     305 [ #  # ][ #  # ]:          0 :             else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) )
                 [ #  # ]
     306                 :            :             {
     307                 :            :                 // Spezialfall: Attrubt deckt genau den Bereich ab
     308                 :            :                 // => als leeres Attribut behalten.
     309 [ #  # ][ #  # ]:          0 :                 if ( ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) )
                 [ #  # ]
     310                 :          0 :                     pAttrib->GetEnd() = nIndex; // leer
     311                 :            :                 else
     312                 :          0 :                     bDelAttr = sal_True;
     313                 :            :             }
     314                 :            :             // 2. Attribut beginnt davor, endet drinnen oder dahinter...
     315 [ #  # ][ #  # ]:          0 :             else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
                 [ #  # ]
     316                 :            :             {
     317         [ #  # ]:          0 :                 if ( pAttrib->GetEnd() <= nEndChanges ) // endet drinnen
     318                 :          0 :                     pAttrib->GetEnd() = nIndex;
     319                 :            :                 else
     320                 :          0 :                     pAttrib->Collaps( nDeleted );       // endet dahinter
     321                 :            :             }
     322                 :            :             // 3. Attribut beginnt drinnen, endet dahinter...
     323 [ #  # ][ #  # ]:          0 :             else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) )
                 [ #  # ]
     324                 :            :             {
     325                 :            :                 // Features duerfen nicht expandieren!
     326                 :          0 :                 pAttrib->GetStart() = nEndChanges;
     327                 :          0 :                 pAttrib->MoveBackward( nDeleted );
     328                 :            :             }
     329                 :            :         }
     330                 :            : 
     331                 :            :         DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut verdreht!" );
     332                 :            :         DBG_ASSERT( ( pAttrib->GetEnd() <= maText.Len()) || bDelAttr, "Collaps: Attrib groesser als Absatz!" );
     333         [ #  # ]:          0 :         if ( bDelAttr /* || pAttrib->IsEmpty() */ )
     334                 :            :         {
     335                 :          0 :             bResort = sal_True;
     336                 :          0 :             maCharAttribs.RemoveAttrib( nAttr );
     337         [ #  # ]:          0 :             delete pAttrib;
     338                 :          0 :             nAttr--;
     339                 :            :         }
     340         [ #  # ]:          0 :         else if ( pAttrib->IsEmpty() )
     341                 :          0 :             maCharAttribs.HasEmptyAttribs() = sal_True;
     342                 :            :     }
     343                 :            : 
     344         [ #  # ]:          0 :     if ( bResort )
     345                 :          0 :         maCharAttribs.ResortAttribs();
     346                 :            : }
     347                 :            : 
     348                 :         52 : void TextNode::InsertText( sal_uInt16 nPos, const String& rText )
     349                 :            : {
     350                 :         52 :     maText.Insert( rText, nPos );
     351                 :         52 :     ExpandAttribs( nPos, rText.Len() );
     352                 :         52 : }
     353                 :            : 
     354                 :          0 : void TextNode::InsertText( sal_uInt16 nPos, sal_Unicode c )
     355                 :            : {
     356                 :          0 :     maText.Insert( c, nPos );
     357                 :          0 :     ExpandAttribs( nPos, 1 );
     358                 :          0 : }
     359                 :            : 
     360                 :          0 : void TextNode::RemoveText( sal_uInt16 nPos, sal_uInt16 nChars )
     361                 :            : {
     362                 :          0 :     maText.Erase( nPos, nChars );
     363                 :          0 :     CollapsAttribs( nPos, nChars );
     364                 :          0 : }
     365                 :            : 
     366                 :          0 : TextNode* TextNode::Split( sal_uInt16 nPos, sal_Bool bKeepEndingAttribs )
     367                 :            : {
     368         [ #  # ]:          0 :     String aNewText;
     369         [ #  # ]:          0 :     if ( nPos < maText.Len() )
     370                 :            :     {
     371 [ #  # ][ #  # ]:          0 :         aNewText = maText.Copy( nPos );
                 [ #  # ]
     372         [ #  # ]:          0 :         maText.Erase( nPos );
     373                 :            :     }
     374 [ #  # ][ #  # ]:          0 :     TextNode* pNew = new TextNode( aNewText );
     375                 :            : 
     376         [ #  # ]:          0 :     for ( sal_uInt16 nAttr = 0; nAttr < maCharAttribs.Count(); nAttr++ )
     377                 :            :     {
     378         [ #  # ]:          0 :         TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr );
     379         [ #  # ]:          0 :         if ( pAttrib->GetEnd() < nPos )
     380                 :            :         {
     381                 :            :             // bleiben unveraendert....
     382                 :            :             ;
     383                 :            :         }
     384         [ #  # ]:          0 :         else if ( pAttrib->GetEnd() == nPos )
     385                 :            :         {
     386                 :            :             // muessen als leeres Attribut kopiert werden.
     387                 :            :             // !FindAttrib nur sinnvoll, wenn Rueckwaerts durch Liste!
     388 [ #  # ][ #  # ]:          0 :             if ( bKeepEndingAttribs && !pNew->maCharAttribs.FindAttrib( pAttrib->Which(), 0 ) )
         [ #  # ][ #  # ]
     389                 :            :             {
     390 [ #  # ][ #  # ]:          0 :                 TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib );
     391                 :          0 :                 pNewAttrib->GetStart() = 0;
     392                 :          0 :                 pNewAttrib->GetEnd() = 0;
     393         [ #  # ]:          0 :                 pNew->maCharAttribs.InsertAttrib( pNewAttrib );
     394                 :            :             }
     395                 :            :         }
     396 [ #  # ][ #  # ]:          0 :         else if ( pAttrib->IsInside( nPos ) || ( !nPos && !pAttrib->GetStart() ) )
         [ #  # ][ #  # ]
     397                 :            :         {
     398                 :            :             // Wenn ganz vorne gecuttet wird, muss das Attribut erhalten bleiben!
     399                 :            :             // muessen kopiert und geaendert werden
     400 [ #  # ][ #  # ]:          0 :             TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib );
     401                 :          0 :             pNewAttrib->GetStart() = 0;
     402                 :          0 :             pNewAttrib->GetEnd() = pAttrib->GetEnd()-nPos;
     403         [ #  # ]:          0 :             pNew->maCharAttribs.InsertAttrib( pNewAttrib );
     404                 :            :             // stutzen:
     405                 :          0 :             pAttrib->GetEnd() = nPos;
     406                 :            :         }
     407                 :            :         else
     408                 :            :         {
     409                 :            :             DBG_ASSERT( pAttrib->GetStart() >= nPos, "Start < nPos!" );
     410                 :            :             DBG_ASSERT( pAttrib->GetEnd() >= nPos, "End < nPos!" );
     411                 :            :             // alle dahinter verschieben in den neuen Node (this)
     412         [ #  # ]:          0 :             maCharAttribs.RemoveAttrib( nAttr );
     413         [ #  # ]:          0 :             pNew->maCharAttribs.InsertAttrib( pAttrib );
     414                 :          0 :             pAttrib->GetStart() = pAttrib->GetStart() - nPos;
     415                 :          0 :             pAttrib->GetEnd() = pAttrib->GetEnd() - nPos;
     416                 :          0 :             nAttr--;
     417                 :            :         }
     418                 :            :     }
     419         [ #  # ]:          0 :     return pNew;
     420                 :            : }
     421                 :            : 
     422                 :          0 : void TextNode::Append( const TextNode& rNode )
     423                 :            : {
     424                 :          0 :     sal_uInt16 nOldLen = maText.Len();
     425                 :            : 
     426                 :          0 :     maText += rNode.GetText();
     427                 :            : 
     428                 :          0 :     const sal_uInt16 nAttribs = rNode.GetCharAttribs().Count();
     429         [ #  # ]:          0 :     for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
     430                 :            :     {
     431                 :          0 :         TextCharAttrib* pAttrib = rNode.GetCharAttribs().GetAttrib( nAttr );
     432                 :          0 :         sal_Bool bMelted = sal_False;
     433         [ #  # ]:          0 :         if ( pAttrib->GetStart() == 0 )
     434                 :            :         {
     435                 :            :             // Evtl koennen Attribute zusammengefasst werden:
     436                 :          0 :             sal_uInt16 nTmpAttribs = maCharAttribs.Count();
     437         [ #  # ]:          0 :             for ( sal_uInt16 nTmpAttr = 0; nTmpAttr < nTmpAttribs; nTmpAttr++ )
     438                 :            :             {
     439                 :          0 :                 TextCharAttrib* pTmpAttrib = maCharAttribs.GetAttrib( nTmpAttr );
     440                 :            : 
     441         [ #  # ]:          0 :                 if ( pTmpAttrib->GetEnd() == nOldLen )
     442                 :            :                 {
     443   [ #  #  #  # ]:          0 :                     if ( ( pTmpAttrib->Which() == pAttrib->Which() ) &&
                 [ #  # ]
     444                 :          0 :                          ( pTmpAttrib->GetAttr() == pAttrib->GetAttr() ) )
     445                 :            :                     {
     446                 :          0 :                         pTmpAttrib->GetEnd() =
     447                 :          0 :                             pTmpAttrib->GetEnd() + pAttrib->GetLen();
     448                 :          0 :                         bMelted = sal_True;
     449                 :          0 :                         break;  // es kann nur eins von der Sorte an der Stelle geben
     450                 :            :                     }
     451                 :            :                 }
     452                 :            :             }
     453                 :            :         }
     454                 :            : 
     455         [ #  # ]:          0 :         if ( !bMelted )
     456                 :            :         {
     457         [ #  # ]:          0 :             TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib );
     458                 :          0 :             pNewAttrib->GetStart() = pNewAttrib->GetStart() + nOldLen;
     459                 :          0 :             pNewAttrib->GetEnd() = pNewAttrib->GetEnd() + nOldLen;
     460                 :          0 :             maCharAttribs.InsertAttrib( pNewAttrib );
     461                 :            :         }
     462                 :            :     }
     463                 :          0 : }
     464                 :            : 
     465                 :            : // -------------------------------------------------------------------------
     466                 :            : // (+) class TextDoc
     467                 :            : // -------------------------------------------------------------------------
     468                 :            : 
     469                 :         90 : TextDoc::TextDoc()
     470                 :            : {
     471                 :         90 :     mnLeftMargin = 0;
     472                 :         90 : };
     473                 :            : 
     474                 :         90 : TextDoc::~TextDoc()
     475                 :            : {
     476         [ +  - ]:         90 :     DestroyTextNodes();
     477                 :         90 : }
     478                 :            : 
     479                 :        128 : void TextDoc::Clear()
     480                 :            : {
     481                 :        128 :     DestroyTextNodes();
     482                 :        128 : }
     483                 :            : 
     484                 :        218 : void TextDoc::DestroyTextNodes()
     485                 :            : {
     486         [ +  + ]:        436 :     for ( sal_uLong nNode = 0; nNode < maTextNodes.Count(); nNode++ )
     487         [ +  - ]:        218 :         delete maTextNodes.GetObject( nNode );
     488                 :        218 :     maTextNodes.clear();
     489                 :        218 : }
     490                 :            : 
     491                 :          0 : String TextDoc::GetText( const sal_Unicode* pSep ) const
     492                 :            : {
     493         [ #  # ]:          0 :     sal_uLong nLen = GetTextLen( pSep );
     494                 :          0 :     sal_uLong nNodes = maTextNodes.Count();
     495                 :            : 
     496         [ #  # ]:          0 :     if ( nLen > STRING_MAXLEN )
     497                 :            :     {
     498                 :            :         OSL_FAIL( "Text zu gross fuer String" );
     499         [ #  # ]:          0 :         return String();
     500                 :            :     }
     501                 :            : 
     502         [ #  # ]:          0 :     String aASCIIText;
     503                 :          0 :     sal_uLong nLastNode = nNodes-1;
     504         [ #  # ]:          0 :     for ( sal_uLong nNode = 0; nNode < nNodes; nNode++ )
     505                 :            :     {
     506         [ #  # ]:          0 :         TextNode* pNode = maTextNodes.GetObject( nNode );
     507         [ #  # ]:          0 :         String aTmp( pNode->GetText() );
     508         [ #  # ]:          0 :         aASCIIText += aTmp;
     509 [ #  # ][ #  # ]:          0 :         if ( pSep && ( nNode != nLastNode ) )
     510         [ #  # ]:          0 :             aASCIIText += pSep;
     511         [ #  # ]:          0 :     }
     512                 :            : 
     513 [ #  # ][ #  # ]:          0 :     return aASCIIText;
     514                 :            : }
     515                 :            : 
     516                 :          0 : XubString TextDoc::GetText( sal_uLong nPara ) const
     517                 :            : {
     518                 :          0 :     XubString aText;
     519 [ #  # ][ #  # ]:          0 :     TextNode* pNode = ( nPara < maTextNodes.Count() ) ? maTextNodes.GetObject( nPara ) : 0;
     520         [ #  # ]:          0 :     if ( pNode )
     521         [ #  # ]:          0 :         aText = pNode->GetText();
     522                 :            : 
     523                 :          0 :     return aText;
     524                 :            : }
     525                 :            : 
     526                 :            : 
     527                 :          0 : sal_uLong TextDoc::GetTextLen( const xub_Unicode* pSep, const TextSelection* pSel ) const
     528                 :            : {
     529                 :          0 :     sal_uLong nLen = 0;
     530                 :          0 :     sal_uLong nNodes = maTextNodes.Count();
     531         [ #  # ]:          0 :     if ( nNodes )
     532                 :            :     {
     533                 :          0 :         sal_uLong nStartNode = 0;
     534                 :          0 :         sal_uLong nEndNode = nNodes-1;
     535         [ #  # ]:          0 :         if ( pSel )
     536                 :            :         {
     537                 :          0 :             nStartNode = pSel->GetStart().GetPara();
     538                 :          0 :             nEndNode = pSel->GetEnd().GetPara();
     539                 :            :         }
     540                 :            : 
     541         [ #  # ]:          0 :         for ( sal_uLong nNode = nStartNode; nNode <= nEndNode; nNode++ )
     542                 :            :         {
     543                 :          0 :             TextNode* pNode = maTextNodes.GetObject( nNode );
     544                 :            : 
     545                 :          0 :             sal_uInt16 nS = 0;
     546                 :          0 :             sal_uLong nE = pNode->GetText().Len();
     547 [ #  # ][ #  # ]:          0 :             if ( pSel && ( nNode == pSel->GetStart().GetPara() ) )
                 [ #  # ]
     548                 :          0 :                 nS = pSel->GetStart().GetIndex();
     549 [ #  # ][ #  # ]:          0 :             if ( pSel && ( nNode == pSel->GetEnd().GetPara() ) )
                 [ #  # ]
     550                 :          0 :                 nE = pSel->GetEnd().GetIndex();
     551                 :            : 
     552                 :          0 :             nLen += ( nE - nS );
     553                 :            :         }
     554                 :            : 
     555         [ #  # ]:          0 :         if ( pSep )
     556                 :          0 :             nLen += (nEndNode-nStartNode) * rtl_ustr_getLength(pSep);
     557                 :            :     }
     558                 :            : 
     559                 :          0 :     return nLen;
     560                 :            : }
     561                 :            : 
     562                 :          0 : TextPaM TextDoc::InsertText( const TextPaM& rPaM, xub_Unicode c )
     563                 :            : {
     564                 :            :     DBG_ASSERT( c != 0x0A, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
     565                 :            :     DBG_ASSERT( c != 0x0D, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
     566                 :            : 
     567                 :          0 :     TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() );
     568                 :          0 :     pNode->InsertText( rPaM.GetIndex(), c );
     569                 :            : 
     570                 :          0 :     TextPaM aPaM( rPaM.GetPara(), rPaM.GetIndex()+1 );
     571                 :          0 :     return aPaM;
     572                 :            : }
     573                 :            : 
     574                 :         52 : TextPaM TextDoc::InsertText( const TextPaM& rPaM, const XubString& rStr )
     575                 :            : {
     576                 :            :     DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
     577                 :            :     DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
     578                 :            : 
     579                 :         52 :     TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() );
     580                 :         52 :     pNode->InsertText( rPaM.GetIndex(), rStr );
     581                 :            : 
     582                 :         52 :     TextPaM aPaM( rPaM.GetPara(), rPaM.GetIndex()+rStr.Len() );
     583                 :         52 :     return aPaM;
     584                 :            : }
     585                 :            : 
     586                 :          0 : TextPaM TextDoc::InsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs )
     587                 :            : {
     588                 :          0 :     TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() );
     589                 :          0 :     TextNode* pNew = pNode->Split( rPaM.GetIndex(), bKeepEndingAttribs );
     590                 :            : 
     591                 :          0 :     maTextNodes.Insert( pNew, rPaM.GetPara()+1 );
     592                 :            : 
     593                 :          0 :     TextPaM aPaM( rPaM.GetPara()+1, 0 );
     594                 :          0 :     return aPaM;
     595                 :            : }
     596                 :            : 
     597                 :          0 : TextPaM TextDoc::ConnectParagraphs( TextNode* pLeft, TextNode* pRight )
     598                 :            : {
     599                 :          0 :     sal_uInt16 nPrevLen = pLeft->GetText().Len();
     600                 :          0 :     pLeft->Append( *pRight );
     601                 :            : 
     602                 :            :     // der rechte verschwindet.
     603                 :          0 :     sal_uLong nRight = maTextNodes.GetPos( pRight );
     604                 :          0 :     maTextNodes.Remove( nRight );
     605         [ #  # ]:          0 :     delete pRight;
     606                 :            : 
     607                 :          0 :     sal_uLong nLeft = maTextNodes.GetPos( pLeft );
     608                 :          0 :     TextPaM aPaM( nLeft, nPrevLen );
     609                 :          0 :     return aPaM;
     610                 :            : }
     611                 :            : 
     612                 :          0 : TextPaM TextDoc::RemoveChars( const TextPaM& rPaM, sal_uInt16 nChars )
     613                 :            : {
     614                 :          0 :     TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() );
     615                 :          0 :     pNode->RemoveText( rPaM.GetIndex(), nChars );
     616                 :            : 
     617                 :          0 :     return rPaM;
     618                 :            : }
     619                 :            : 
     620                 :          0 : sal_Bool TextDoc::IsValidPaM( const TextPaM& rPaM )
     621                 :            : {
     622         [ #  # ]:          0 :     if ( rPaM.GetPara() >= maTextNodes.Count() )
     623                 :            :     {
     624                 :            :         OSL_FAIL( "PaM: Para out of range" );
     625                 :          0 :         return sal_False;
     626                 :            :     }
     627                 :          0 :     TextNode * pNode = maTextNodes.GetObject( rPaM.GetPara() );
     628         [ #  # ]:          0 :     if ( rPaM.GetIndex() > pNode->GetText().Len() )
     629                 :            :     {
     630                 :            :         OSL_FAIL( "PaM: Index out of range" );
     631                 :          0 :         return sal_False;
     632                 :            :     }
     633                 :          0 :     return sal_True;
     634                 :            : }
     635                 :            : 
     636                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10