LCOV - code coverage report
Current view: top level - sw/source/core/txtnode - thints.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 919 1214 75.7 %
Date: 2012-08-25 Functions: 43 52 82.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1038 1944 53.4 %

           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 <hintids.hxx>
      30                 :            : #include <sot/factory.hxx>
      31                 :            : #include <editeng/xmlcnitm.hxx>
      32                 :            : #include <svl/whiter.hxx>
      33                 :            : #include <svl/itemiter.hxx>
      34                 :            : #include <svl/stylepool.hxx>
      35                 :            : #include <editeng/fontitem.hxx>
      36                 :            : #include <editeng/langitem.hxx>
      37                 :            : #include <editeng/emphitem.hxx>
      38                 :            : #include <editeng/charscaleitem.hxx>
      39                 :            : #include <editeng/charrotateitem.hxx>
      40                 :            : #include <editeng/lrspitem.hxx>
      41                 :            : #include <txtinet.hxx>
      42                 :            : #include <txtflcnt.hxx>
      43                 :            : #include <fmtfld.hxx>
      44                 :            : #include <fmtanchr.hxx>
      45                 :            : #include <fmtinfmt.hxx>
      46                 :            : #include <txtatr.hxx>
      47                 :            : #include <fchrfmt.hxx>
      48                 :            : #include <fmtautofmt.hxx>
      49                 :            : #include <fmtflcnt.hxx>
      50                 :            : #include <fmtftn.hxx>
      51                 :            : #include <txttxmrk.hxx>
      52                 :            : #include <txtrfmrk.hxx>
      53                 :            : #include <txtftn.hxx>
      54                 :            : #include <txtfld.hxx>
      55                 :            : #include <charatr.hxx>
      56                 :            : #include <charfmt.hxx>
      57                 :            : #include <frmfmt.hxx>
      58                 :            : #include <ftnidx.hxx>
      59                 :            : #include <fmtruby.hxx>
      60                 :            : #include <fmtmeta.hxx>
      61                 :            : #include <breakit.hxx>
      62                 :            : #include <doc.hxx>
      63                 :            : #include <IDocumentUndoRedo.hxx>
      64                 :            : #include <fldbas.hxx>
      65                 :            : #include <pam.hxx>
      66                 :            : #include <ndtxt.hxx>
      67                 :            : #include <txtfrm.hxx>
      68                 :            : #include <rolbck.hxx>           // fuer SwRegHistory
      69                 :            : #include <ddefld.hxx>
      70                 :            : #include <docufld.hxx>
      71                 :            : #include <expfld.hxx>
      72                 :            : #include <usrfld.hxx>
      73                 :            : #include <poolfmt.hxx>
      74                 :            : #include <swfont.hxx>
      75                 :            : #include <istyleaccess.hxx>
      76                 :            : // OD 26.06.2003 #108784#
      77                 :            : #include <dcontact.hxx>
      78                 :            : #include <docsh.hxx>
      79                 :            : #include <svl/smplhint.hxx>
      80                 :            : #include <algorithm>
      81                 :            : #include <map>
      82                 :            : 
      83                 :            : #ifdef DBG_UTIL
      84                 :            : #define CHECK    Check();
      85                 :            : #else
      86                 :            : #define CHECK
      87                 :            : #endif
      88                 :            : 
      89                 :            : using namespace ::com::sun::star::i18n;
      90                 :            : 
      91                 :            : 
      92                 :       6621 : SwpHints::SwpHints()
      93                 :            :     : m_pHistory(0)
      94                 :            :     , m_bFontChange(true)
      95                 :            :     , m_bInSplitNode(false)
      96                 :            :     , m_bCalcHiddenParaField(false)
      97                 :            :     , m_bHasHiddenParaField(false)
      98                 :            :     , m_bFootnote(false)
      99                 :       6621 :     , m_bDDEFields(false)
     100                 :            : {
     101                 :       6621 : }
     102                 :            : 
     103                 :            : struct TxtAttrDeleter
     104                 :            : {
     105                 :            :     SwAttrPool & m_rPool;
     106                 :          4 :     TxtAttrDeleter( SwDoc & rDoc ) : m_rPool( rDoc.GetAttrPool() ) { }
     107                 :          4 :     void operator() (SwTxtAttr * const pAttr)
     108                 :            :     {
     109   [ -  +  #  # ]:          4 :         if (RES_TXTATR_META == pAttr->Which() ||
                 [ +  - ]
     110                 :          0 :             RES_TXTATR_METAFIELD == pAttr->Which())
     111                 :            :         {
     112                 :          4 :             static_cast<SwTxtMeta *>(pAttr)->ChgTxtNode(0); // prevents ASSERT
     113                 :            :         }
     114                 :          4 :         SwTxtAttr::Destroy( pAttr, m_rPool );
     115                 :          4 :     }
     116                 :            : };
     117                 :            : 
     118                 :            : struct TxtAttrContains
     119                 :            : {
     120                 :            :     xub_StrLen m_nPos;
     121                 :         60 :     TxtAttrContains( const xub_StrLen nPos ) : m_nPos( nPos ) { }
     122                 :         78 :     bool operator() (SwTxtAttrEnd * const pAttr)
     123                 :            :     {
     124 [ +  + ][ +  + ]:         78 :         return (*pAttr->GetStart() < m_nPos) && (m_nPos < *pAttr->GetEnd());
     125                 :            :     }
     126                 :            : };
     127                 :            : 
     128                 :            : // a:       |-----|
     129                 :            : // b:
     130                 :            : //    |---|               => valid: b before a
     131                 :            : //    |-----|             => valid: start == end; b before a
     132                 :            : //    |---------|         => invalid: overlap (1)
     133                 :            : //    |-----------|       => valid: same end; b around a
     134                 :            : //    |-----------------| => valid: b around a
     135                 :            : //          |---|         => valid; same start; b within a
     136                 :            : //          |-----|       => valid; same start and end; b around or within a?
     137                 :            : //          |-----------| => valid: same start: b around a
     138                 :            : //            |-|         => valid: b within a
     139                 :            : //            |---|       => valid: same end; b within a
     140                 :            : //            |---------| => invalid: overlap (2)
     141                 :            : //                |-----| => valid: end == start; b after a
     142                 :            : //                  |---| => valid: b after a
     143                 :            : // ===> 2 invalid overlap cases
     144                 :            : static
     145                 :       2156 : bool isOverlap(const xub_StrLen nStart1, const xub_StrLen nEnd1,
     146                 :            :                const xub_StrLen nStart2, const xub_StrLen nEnd2)
     147                 :            : {
     148                 :            :     return
     149                 :            :         ((nStart1 > nStart2) && (nStart1 < nEnd2) && (nEnd1 > nEnd2))  // (1)
     150 [ +  + ][ +  + ]:       2156 :      || ((nStart1 < nStart2) && (nStart2 < nEnd1) && (nEnd1 < nEnd2)); // (2)
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
     151                 :            : }
     152                 :            : 
     153                 :            : /// #i106930#: now asymmetric: empty hint1 is _not_ nested, but empty hint2 is
     154                 :            : static
     155                 :       2070 : bool isNestedAny(const xub_StrLen nStart1, const xub_StrLen nEnd1,
     156                 :            :                  const xub_StrLen nStart2, const xub_StrLen nEnd2)
     157                 :            : {
     158                 :            :     return ((nStart1 == nStart2) || (nEnd1 == nEnd2))
     159                 :            :         // same start/end: nested except if hint1 empty and hint2 not empty
     160                 :            :         ? (nStart1 != nEnd1) || (nStart2 == nEnd2)
     161 [ +  + ][ +  + ]:       2070 :         : ((nStart1 < nStart2) ? (nEnd1 >= nEnd2) : (nEnd1 <= nEnd2));
         [ +  + ][ +  + ]
                 [ +  + ]
     162                 :            : }
     163                 :            : 
     164                 :            : static
     165                 :        641 : bool isSelfNestable(const sal_uInt16 nWhich)
     166                 :            : {
     167 [ +  + ][ +  + ]:        641 :     if ((RES_TXTATR_INETFMT  == nWhich) ||
     168                 :            :         (RES_TXTATR_CJK_RUBY == nWhich))
     169                 :        447 :         return false;
     170                 :            :    OSL_ENSURE((RES_TXTATR_META  == nWhich) ||
     171                 :            :            (RES_TXTATR_METAFIELD  == nWhich), "???");
     172                 :        641 :     return true;
     173                 :            : }
     174                 :            : 
     175                 :            : static
     176                 :        144 : bool isSplittable(const sal_uInt16 nWhich)
     177                 :            : {
     178 [ +  + ][ +  + ]:        144 :     if ((RES_TXTATR_INETFMT  == nWhich) ||
     179                 :            :         (RES_TXTATR_CJK_RUBY == nWhich))
     180                 :         82 :         return true;
     181                 :            :    OSL_ENSURE((RES_TXTATR_META  == nWhich) ||
     182                 :            :            (RES_TXTATR_METAFIELD  == nWhich), "???");
     183                 :        144 :     return false;
     184                 :            : }
     185                 :            : 
     186                 :            : enum Split_t { FAIL, SPLIT_NEW, SPLIT_OTHER };
     187                 :            : /**
     188                 :            :   Calculate splitting policy for overlapping hints, based on what kind of
     189                 :            :   hint is inserted, and what kind of existing hint overlaps.
     190                 :            :   */
     191                 :            : static Split_t
     192                 :         86 : splitPolicy(const sal_uInt16 nWhichNew, const sal_uInt16 nWhichOther)
     193                 :            : {
     194         [ +  + ]:         86 :     if (!isSplittable(nWhichOther))
     195                 :            :     {
     196         [ +  + ]:         58 :         if (!isSplittable(nWhichNew))
     197                 :          4 :             return FAIL;
     198                 :            :         else
     199                 :         54 :             return SPLIT_NEW;
     200                 :            :     }
     201                 :            :     else
     202                 :            :     {
     203 [ +  + ][ +  + ]:         28 :         if ((RES_TXTATR_INETFMT  == nWhichNew) &&
     204                 :            :             (RES_TXTATR_CJK_RUBY == nWhichOther))
     205                 :          6 :             return SPLIT_NEW;
     206                 :            :         else
     207                 :         86 :             return SPLIT_OTHER;
     208                 :            :     }
     209                 :            : }
     210                 :            : 
     211                 :        115 : void SwTxtINetFmt::InitINetFmt(SwTxtNode & rNode)
     212                 :            : {
     213                 :        115 :     ChgTxtNode(&rNode);
     214                 :            :     SwCharFmt * const pFmt(
     215                 :        115 :          rNode.GetDoc()->GetCharFmtFromPool(RES_POOLCHR_INET_NORMAL) );
     216                 :        115 :     pFmt->Add( this );
     217                 :        115 : }
     218                 :            : 
     219                 :        386 : void SwTxtRuby::InitRuby(SwTxtNode & rNode)
     220                 :            : {
     221                 :        386 :     ChgTxtNode(&rNode);
     222                 :            :     SwCharFmt * const pFmt(
     223                 :        386 :         rNode.GetDoc()->GetCharFmtFromPool(RES_POOLCHR_RUBYTEXT) );
     224                 :        386 :     pFmt->Add( this );
     225                 :        386 : }
     226                 :            : 
     227                 :            : /**
     228                 :            :   Create a new nesting text hint.
     229                 :            :  */
     230                 :            : static SwTxtAttrNesting *
     231                 :         82 : MakeTxtAttrNesting(SwTxtNode & rNode, SwTxtAttrNesting & rNesting,
     232                 :            :         const xub_StrLen nStart, const xub_StrLen nEnd)
     233                 :            : {
     234                 :            :     SwTxtAttr * const pNew( MakeTxtAttr(
     235                 :         82 :             *rNode.GetDoc(), rNesting.GetAttr(), nStart, nEnd ) );
     236      [ +  +  - ]:         82 :     switch (pNew->Which())
     237                 :            :     {
     238                 :            :         case RES_TXTATR_INETFMT:
     239                 :            :         {
     240                 :         26 :             static_cast<SwTxtINetFmt*>(pNew)->InitINetFmt(rNode);
     241                 :         26 :             break;
     242                 :            :         }
     243                 :            :         case RES_TXTATR_CJK_RUBY:
     244                 :            :         {
     245                 :         56 :             static_cast<SwTxtRuby*>(pNew)->InitRuby(rNode);
     246                 :         56 :             break;
     247                 :            :         }
     248                 :            :         default:
     249                 :            :             OSL_FAIL("MakeTxtAttrNesting: what the hell is that?");
     250                 :          0 :             break;
     251                 :            :     }
     252                 :         82 :     return static_cast<SwTxtAttrNesting*>(pNew);
     253                 :            : }
     254                 :            : 
     255                 :            : typedef ::std::vector<SwTxtAttrNesting *> NestList_t;
     256                 :            : 
     257                 :            : static void
     258                 :         60 : lcl_DoSplitNew(NestList_t & rSplits, SwTxtNode & rNode,
     259                 :            :     const xub_StrLen nNewStart,
     260                 :            :     const xub_StrLen nOtherStart, const xub_StrLen nOtherEnd, bool bOtherDummy)
     261                 :            : {
     262                 :         60 :     const bool bSplitAtStart(nNewStart < nOtherStart);
     263         [ +  + ]:         60 :     const xub_StrLen nSplitPos( (bSplitAtStart) ? nOtherStart : nOtherEnd );
     264                 :            :     // first find the portion that is split (not necessarily the last one!)
     265                 :            :     NestList_t::iterator const iter(
     266                 :            :         ::std::find_if( rSplits.begin(), rSplits.end(),
     267         [ +  - ]:         60 :             TxtAttrContains(nSplitPos) ) );
     268 [ +  - ][ +  + ]:         60 :     if (iter != rSplits.end()) // already split here?
     269                 :            :     {
     270                 :            :         const xub_StrLen nStartPos( // skip other's dummy character!
     271 [ +  + ][ +  + ]:         56 :             (bSplitAtStart && bOtherDummy) ? nSplitPos + 1 : nSplitPos );
     272                 :            :         SwTxtAttrNesting * const pNew( MakeTxtAttrNesting(
     273 [ +  - ][ +  - ]:         56 :                 rNode, **iter, nStartPos, *(*iter)->GetEnd() ) );
     274         [ +  - ]:         56 :         *(*iter)->GetEnd() = nSplitPos;
     275 [ +  - ][ +  - ]:         56 :         rSplits.insert(iter + 1, pNew);
     276                 :            :     }
     277                 :         60 : }
     278                 :            : 
     279                 :            : /**
     280                 :            :   Insert nesting hint into the hints array. Also calls NoteInHistory.
     281                 :            :   @param    rNewHint    the hint to be inserted (must not overlap existing!)
     282                 :            :  */
     283                 :        725 : void SwpHints::InsertNesting(SwTxtAttrNesting & rNewHint)
     284                 :            : {
     285                 :        725 :     SwpHintsArray::Insert(& rNewHint);
     286                 :        725 :     NoteInHistory( & rNewHint, true );
     287                 :        725 : }
     288                 :            : 
     289                 :            : /**
     290                 :            : 
     291                 :            : The following hints correspond to well-formed XML elements in ODF:
     292                 :            : RES_TXTATR_INETFMT, RES_TXTATR_CJK_RUBY, RES_TXTATR_META, RES_TXTATR_METAFIELD
     293                 :            : 
     294                 :            : The writer core must ensure that these do not overlap; if they did,
     295                 :            : the document would not be storable as ODF.
     296                 :            : 
     297                 :            : Also, a Hyperlink must not be nested within another Hyperlink,
     298                 :            : and a Ruby must not be nested within another Ruby.
     299                 :            : 
     300                 :            : The ODF export in xmloff will only put a hyperlink into a ruby, never a ruby
     301                 :            : into a hyperlink.
     302                 :            : 
     303                 :            : Unfortunately the UNO API for Hyperlink and Ruby consists of the properties
     304                 :            : Hyperlink* and Ruby* of the css.text.CharacterProperties service.  In other
     305                 :            : words, they are treated as formatting attributes, not as content entites.
     306                 :            : Furthermore, for API users it is not possible to easily test whether a certain
     307                 :            : range would be overlapping with other nested attributes, and most importantly,
     308                 :            : <em>which ones</em>, so we can hardly refuse to insert these in cases of
     309                 :            : overlap.
     310                 :            : 
     311                 :            : It is possible to split Hyperlink and Ruby into multiple portions, such that
     312                 :            : the result is properly nested.
     313                 :            : 
     314                 :            : meta and meta-field must not be split, because they have xml:id.
     315                 :            : 
     316                 :            : These constraints result in the following design:
     317                 :            : 
     318                 :            : RES_TXTATR_INETFMT:
     319                 :            :     always succeeds
     320                 :            :     inserts n attributes split at RES_TXTATR_CJK_RUBY, RES_TXTATR_META,
     321                 :            :         RES_TXTATR_METAFIELD
     322                 :            :     may replace existing RES_TXTATR_INETFMT at overlap
     323                 :            : RES_TXTATR_CJK_RUBY:
     324                 :            :     always succeeds
     325                 :            :     inserts n attributes split at RES_TXTATR_META, RES_TXTATR_METAFIELD
     326                 :            :     may replace existing RES_TXTATR_CJK_RUBY at overlap
     327                 :            :     may split existing overlapping RES_TXTATR_INETFMT
     328                 :            : RES_TXTATR_META:
     329                 :            :     may fail if overlapping existing RES_TXTATR_META/RES_TXTATR_METAFIELD
     330                 :            :     may split existing overlapping RES_TXTATR_INETFMT or RES_TXTATR_CJK_RUBY
     331                 :            :     inserts 1 attribute
     332                 :            : RES_TXTATR_METAFIELD:
     333                 :            :     may fail if overlapping existing RES_TXTATR_META/RES_TXTATR_METAFIELD
     334                 :            :     may split existing overlapping RES_TXTATR_INETFMT or RES_TXTATR_CJK_RUBY
     335                 :            :     inserts 1 attribute
     336                 :            : 
     337                 :            : The nesting is expressed by the position of the hints.
     338                 :            : RES_TXTATR_META and RES_TXTATR_METAFIELD have a CH_TXTATR, and there can
     339                 :            : only be one such hint starting and ending at a given position.
     340                 :            : Only RES_TXTATR_INETFMT and RES_TXTATR_CJK_RUBY lack a CH_TXTATR.
     341                 :            : The interpretation given is that RES_TXTATR_CJK_RUBY is always around
     342                 :            : a RES_TXTATR_INETFMT at the same start and end position (which corresponds
     343                 :            : with the UNO API).
     344                 :            : Both of these are always around a nesting hint with CH_TXTATR at the same
     345                 :            : start and end position (if they should be inside, then the start should be
     346                 :            : after the CH_TXTATR).
     347                 :            : It would probably be a bad idea to add another nesting hint without
     348                 :            : CH_TXTATR; on the other hand, it would be difficult adding a CH_TXTATR to
     349                 :            : RES_TXTATR_INETFMT and RES_TXTATR_CJK_RUBY, due to the overwriting and
     350                 :            : splitting of exising hints that is necessary for backward compatibility.
     351                 :            : 
     352                 :            :     @param rNode    the text node
     353                 :            :     @param rHint    the hint to be inserted
     354                 :            :     @returns        true iff hint was successfully inserted
     355                 :            : */
     356                 :            : bool
     357                 :        641 : SwpHints::TryInsertNesting( SwTxtNode & rNode, SwTxtAttrNesting & rNewHint )
     358                 :            : {
     359                 :            : //    INVARIANT:  the nestable hints in the array are properly nested
     360         [ +  - ]:        641 :     const sal_uInt16 nNewWhich( rNewHint.Which() );
     361                 :        641 :     const xub_StrLen nNewStart( *rNewHint.GetStart() );
     362         [ +  - ]:        641 :     const xub_StrLen nNewEnd  ( *rNewHint.GetEnd()   );
     363                 :            : //???    const bool bNoLengthAttribute( nNewStart == nNewEnd );
     364                 :        641 :     const bool bNewSelfNestable( isSelfNestable(nNewWhich) );
     365                 :            : 
     366                 :            :     OSL_ENSURE( (RES_TXTATR_INETFMT   == nNewWhich) ||
     367                 :            :             (RES_TXTATR_CJK_RUBY  == nNewWhich) ||
     368                 :            :             (RES_TXTATR_META      == nNewWhich) ||
     369                 :            :             (RES_TXTATR_METAFIELD == nNewWhich),
     370                 :            :         "TryInsertNesting: Expecting INETFMT or RUBY or META or METAFIELD" );
     371                 :            : 
     372         [ +  - ]:        641 :     NestList_t OverlappingExisting; // existing hints to be split
     373         [ +  - ]:        641 :     NestList_t OverwrittenExisting; // existing hints to be replaced
     374         [ +  - ]:        641 :     NestList_t SplitNew;            // new hints to be inserted
     375                 :            : 
     376         [ +  - ]:        641 :     SplitNew.push_back(& rNewHint);
     377                 :            : 
     378                 :            :     // pass 1: split the inserted hint into fragments if necessary
     379         [ +  + ]:       4298 :     for ( sal_uInt16 i = 0; i < GetEndCount(); ++i )
     380                 :            :     {
     381         [ +  - ]:       3661 :         SwTxtAttr * const pOther = GetEnd(i);
     382                 :            : 
     383         [ +  + ]:       3661 :         if (pOther->IsNesting())
     384                 :            :         {
     385         [ +  - ]:       2156 :             const sal_uInt16 nOtherWhich( pOther->Which() );
     386                 :       2156 :             const xub_StrLen nOtherStart( *(pOther)->GetStart() );
     387         [ +  - ]:       2156 :             const xub_StrLen nOtherEnd  ( *(pOther)->GetEnd()   );
     388         [ +  + ]:       2156 :             if (isOverlap(nNewStart, nNewEnd, nOtherStart, nOtherEnd ))
     389                 :            :             {
     390   [ +  +  +  - ]:         86 :                 switch (splitPolicy(nNewWhich, nOtherWhich))
     391                 :            :                 {
     392                 :            :                     case FAIL:
     393                 :            :                         OSL_TRACE("cannot insert hint: overlap detected");
     394                 :            :                         ::std::for_each(SplitNew.begin(), SplitNew.end(),
     395         [ +  - ]:          4 :                             TxtAttrDeleter(*rNode.GetDoc()));
     396                 :          4 :                         return false;
     397                 :            :                     case SPLIT_NEW:
     398                 :            :                         lcl_DoSplitNew(SplitNew, rNode, nNewStart,
     399         [ +  - ]:         60 :                             nOtherStart, nOtherEnd, pOther->HasDummyChar());
     400                 :         60 :                         break;
     401                 :            :                     case SPLIT_OTHER:
     402                 :            :                         OverlappingExisting.push_back(
     403         [ +  - ]:         22 :                             static_cast<SwTxtAttrNesting*>(pOther));
     404                 :         22 :                         break;
     405                 :            :                     default:
     406                 :            :                         OSL_FAIL("bad code monkey");
     407                 :         82 :                         break;
     408                 :            :                 }
     409                 :            :             }
     410         [ +  + ]:       2070 :             else if (isNestedAny(nNewStart, nNewEnd, nOtherStart, nOtherEnd))
     411                 :            :             {
     412 [ +  + ][ +  + ]:        432 :                 if (!bNewSelfNestable && (nNewWhich == nOtherWhich))
     413                 :            :                 {
     414                 :            :                 // ruby and hyperlink: if there is nesting, _overwrite_
     415                 :            :                 OverwrittenExisting.push_back(
     416         [ +  - ]:        226 :                     static_cast<SwTxtAttrNesting*>(pOther));
     417                 :            :                 }
     418 [ +  + ][ +  + ]:        206 :                 else if ((nNewStart == nOtherStart) && pOther->HasDummyChar())
                 [ +  + ]
     419                 :            :                 {
     420         [ -  + ]:         48 :                     if (rNewHint.HasDummyChar())
     421                 :            :                     {
     422                 :            :                         OSL_FAIL("ERROR: inserting duplicate CH_TXTATR hint");
     423                 :          0 :                         return false;
     424         [ +  + ]:         48 :                     } else if (nNewEnd < nOtherEnd) {
     425                 :            :                         // other has dummy char, new is inside other, but
     426                 :            :                         // new contains the other's dummy char?
     427                 :            :                         // should be corrected because it may lead to problems
     428                 :            :                         // in SwXMeta::createEnumeration
     429                 :            :                         // SplitNew is sorted, so this is the first split
     430                 :          4 :                         xub_StrLen *const pStart(SplitNew.front()->GetStart());
     431                 :            :                         OSL_ENSURE(*pStart == nNewStart, "how did that happen?");
     432                 :        432 :                         *pStart = nNewStart + 1;
     433                 :            :                     }
     434                 :            :                 }
     435                 :            :             }
     436                 :            :         }
     437                 :            :     }
     438                 :            : 
     439                 :            :    OSL_ENSURE(isSplittable(nNewWhich) || SplitNew.size() == 1,
     440                 :            :             "splitting the unsplittable ???");
     441                 :            : 
     442                 :            :     // pass 2: split existing hints that overlap/nest with new hint
     443                 :            :     // do not iterate over hints array, but over remembered set of overlapping
     444                 :            :     // hints, to keep things simple w.r.t. insertion/removal
     445                 :            :     // N.B: if there is a hint that splits the inserted hint, then
     446                 :            :     // that hint would also have already split any hint in OverlappingExisting
     447                 :            :     // so any hint in OverlappingExisting can be split at most by one hint
     448                 :            :     // in SplitNew, or even not at all (this is not true for existing hints
     449                 :            :     // that go _around_ new hint, which is the raison d'^etre for pass 4)
     450 [ +  - ][ +  + ]:       1318 :     for (NestList_t::iterator itOther = OverlappingExisting.begin();
     451                 :        659 :             itOther != OverlappingExisting.end(); ++itOther)
     452                 :            :     {
     453                 :         22 :         const xub_StrLen nOtherStart( *(*itOther)->GetStart() );
     454         [ +  - ]:         22 :         const xub_StrLen nOtherEnd  ( *(*itOther)->GetEnd()   );
     455                 :            : 
     456 [ +  - ][ +  + ]:         92 :         for (NestList_t::iterator itNew = SplitNew.begin();
     457                 :         46 :                 itNew != SplitNew.end(); ++itNew)
     458                 :            :         {
     459                 :         24 :             const xub_StrLen nSplitNewStart( *(*itNew)->GetStart() );
     460         [ +  - ]:         24 :             const xub_StrLen nSplitNewEnd  ( *(*itNew)->GetEnd()   );
     461                 :            :             // 4 cases: within, around, overlap l, overlap r, (OTHER: no action)
     462                 :            :             const bool bRemoveOverlap(
     463 [ +  + ][ +  - ]:         24 :                 !bNewSelfNestable && (nNewWhich == (*itOther)->Which()) );
                 [ +  + ]
     464                 :            : 
     465   [ +  -  +  +  :         24 :             switch (ComparePosition(nSplitNewStart, nSplitNewEnd,
                      + ]
     466                 :         24 :                                     nOtherStart,    nOtherEnd))
     467                 :            :             {
     468                 :            :                 case POS_INSIDE:
     469                 :            :                     {
     470                 :            :                         OSL_ENSURE(!bRemoveOverlap,
     471                 :            :                             "this one should be in OverwrittenExisting?");
     472                 :            :                     }
     473                 :          2 :                     break;
     474                 :            :                 case POS_OUTSIDE:
     475                 :            :                 case POS_EQUAL:
     476                 :            :                     {
     477                 :            :                         OSL_FAIL("existing hint inside new hint: why?");
     478                 :            :                     }
     479                 :          0 :                     break;
     480                 :            :                 case POS_OVERLAP_BEFORE:
     481                 :            :                     {
     482         [ +  - ]:         10 :                         Delete( *itOther ); // this also does NoteInHistory!
     483                 :         10 :                         *(*itOther)->GetStart() = nSplitNewEnd;
     484         [ +  - ]:         10 :                         InsertNesting( **itOther );
     485         [ +  + ]:         10 :                         if (!bRemoveOverlap)
     486                 :            :                         {
     487         [ -  + ]:          6 :                             if ( USHRT_MAX == Count() )
     488                 :            :                             {
     489                 :            :                                 OSL_FAIL("hints array full :-(");
     490                 :          0 :                                 return false;
     491                 :            :                             }
     492                 :            :                             SwTxtAttrNesting * const pOtherLeft(
     493                 :          6 :                                 MakeTxtAttrNesting( rNode, **itOther,
     494         [ +  - ]:          6 :                                     nOtherStart, nSplitNewEnd ) );
     495         [ +  - ]:          6 :                             InsertNesting( *pOtherLeft );
     496                 :            :                         }
     497                 :            :                     }
     498                 :         10 :                     break;
     499                 :            :                 case POS_OVERLAP_BEHIND:
     500                 :            :                     {
     501         [ +  - ]:         10 :                         Delete( *itOther ); // this also does NoteInHistory!
     502         [ +  - ]:         10 :                         *(*itOther)->GetEnd() = nSplitNewStart;
     503         [ +  - ]:         10 :                         InsertNesting( **itOther );
     504         [ +  + ]:         10 :                         if (!bRemoveOverlap)
     505                 :            :                         {
     506         [ -  + ]:          6 :                             if ( USHRT_MAX == Count() )
     507                 :            :                             {
     508                 :            :                                 OSL_FAIL("hints array full :-(");
     509                 :          0 :                                 return false;
     510                 :            :                             }
     511                 :            :                             SwTxtAttrNesting * const pOtherRight(
     512                 :          6 :                                 MakeTxtAttrNesting( rNode, **itOther,
     513         [ +  - ]:          6 :                                     nSplitNewStart, nOtherEnd ) );
     514         [ +  - ]:          6 :                             InsertNesting( *pOtherRight );
     515                 :            :                         }
     516                 :            :                     }
     517                 :         10 :                     break;
     518                 :            :                 default:
     519                 :          2 :                     break; // overlap resolved by splitting new: nothing to do
     520                 :            :             }
     521                 :            :         }
     522                 :            :     }
     523                 :            : 
     524         [ -  + ]:        637 :     if ( USHRT_MAX - SplitNew.size() <= Count() )
     525                 :            :     {
     526                 :            :         OSL_FAIL("hints array full :-(");
     527                 :          0 :         return false;
     528                 :            :     }
     529                 :            : 
     530                 :            :     // pass 3: insert new hints
     531 [ +  - ][ +  + ]:       2660 :     for (NestList_t::iterator iter = SplitNew.begin();
     532                 :       1330 :             iter != SplitNew.end(); ++iter)
     533                 :            :     {
     534         [ +  - ]:        693 :         InsertNesting(**iter);
     535                 :            :     }
     536                 :            : 
     537                 :            :     // pass 4: handle overwritten hints
     538                 :            :     // RES_TXTATR_INETFMT and RES_TXTATR_CJK_RUBY should displace attributes
     539                 :            :     // of the same kind.
     540 [ +  - ][ +  + ]:       1726 :     for (NestList_t::iterator itOther = OverwrittenExisting.begin();
     541                 :        863 :             itOther != OverwrittenExisting.end(); ++itOther)
     542                 :            :     {
     543                 :        226 :         const xub_StrLen nOtherStart( *(*itOther)->GetStart() );
     544         [ +  - ]:        226 :         const xub_StrLen nOtherEnd  ( *(*itOther)->GetEnd()   );
     545                 :            : 
     546                 :            :         // overwritten portion is given by start/end of inserted hint
     547 [ +  + ][ +  - ]:        226 :         if ((nNewStart <= nOtherStart) && (nOtherEnd <= nNewEnd))
     548                 :            :         {
     549         [ +  - ]:        212 :             Delete(*itOther);
     550         [ +  - ]:        212 :             rNode.DestroyAttr( *itOther );
     551                 :            :         }
     552                 :            :         else
     553                 :            :         {
     554                 :            :            OSL_ENSURE((nOtherStart < nNewStart) && (nNewEnd < nOtherEnd), "huh?");
     555                 :            :         // scenario: there is a RUBY, and contained within that a META;
     556                 :            :         // now a RUBY is inserted within the META => the exising RUBY is split:
     557                 :            :         // here it is not possible to simply insert the left/right fragment
     558                 :            :         // of the existing RUBY because they <em>overlap</em> with the META!
     559         [ +  - ]:         14 :             Delete( *itOther ); // this also does NoteInHistory!
     560         [ +  - ]:         14 :             *(*itOther)->GetEnd() = nNewStart;
     561         [ +  - ]:         14 :             bool bSuccess( TryInsertNesting(rNode, **itOther) );
     562                 :            :             OSL_ENSURE(bSuccess, "recursive call 1 failed?");
     563                 :            :             SwTxtAttrNesting * const pOtherRight(
     564                 :            :                 MakeTxtAttrNesting(
     565         [ +  - ]:         14 :                     rNode, **itOther, nNewEnd, nOtherEnd ) );
     566         [ +  - ]:         14 :             bSuccess = TryInsertNesting(rNode, *pOtherRight);
     567                 :            :             OSL_ENSURE(bSuccess, "recursive call 2 failed?");
     568                 :            :             (void)bSuccess;
     569                 :            :         }
     570                 :            : 
     571                 :            :     }
     572                 :            : 
     573                 :        641 :     return true;
     574                 :            : }
     575                 :            : 
     576                 :            : 
     577                 :            : // This function takes care for the following text attribute:
     578                 :            : // RES_TXTATR_CHARFMT, RES_TXTATR_AUTOFMT
     579                 :            : // These attributes have to be handled in a special way (Portion building).
     580                 :            : //
     581                 :            : // The new attribute will be split by any existing RES_TXTATR_AUTOFMT or
     582                 :            : // RES_TXTATR_CHARFMT. The new attribute itself will
     583                 :            : // split any existing RES_TXTATR_AUTOFMT or RES_TXTATR_CHARFMT.
     584                 :            : 
     585                 :      14834 : void SwpHints::BuildPortions( SwTxtNode& rNode, SwTxtAttr& rNewHint,
     586                 :            :         const SetAttrMode nMode )
     587                 :            : {
     588         [ +  - ]:      14834 :     const sal_uInt16 nWhich = rNewHint.Which();
     589                 :            : 
     590                 :      14834 :     const xub_StrLen nThisStart = *rNewHint.GetStart();
     591         [ +  - ]:      14834 :     const xub_StrLen nThisEnd =   *rNewHint.GetEnd();
     592                 :      14834 :     const bool bNoLengthAttribute = nThisStart == nThisEnd;
     593                 :            : 
     594         [ +  - ]:      14834 :     std::vector<SwTxtAttr*> aInsDelHints;
     595                 :      14834 :     std::vector<SwTxtAttr*>::iterator aIter;
     596                 :            : 
     597                 :            :     OSL_ENSURE( RES_TXTATR_CHARFMT == rNewHint.Which() ||
     598                 :            :             RES_TXTATR_AUTOFMT == rNewHint.Which(),
     599                 :            :             "Expecting CHARFMT or AUTOFMT" );
     600                 :            : 
     601                 :            :     //
     602                 :            :     // 2. Find the hints which cover the start and end position
     603                 :            :     // of the new hint. These hints have to be split into two portions:
     604                 :            :     //
     605         [ +  + ]:      14834 :     if ( !bNoLengthAttribute ) // nothing to do for no length attributes
     606                 :            :     {
     607         [ +  + ]:      51578 :         for ( sal_uInt16 i = 0; i < Count(); ++i )
     608                 :            :         {
     609         [ +  - ]:      38660 :             SwTxtAttr* pOther = GetTextHint(i);
     610                 :            : 
     611 [ +  - ][ +  + ]:      77251 :             if ( RES_TXTATR_CHARFMT != pOther->Which() &&
         [ +  + ][ +  + ]
     612         [ +  - ]:      38591 :                  RES_TXTATR_AUTOFMT != pOther->Which() )
     613                 :      17120 :                 continue;
     614                 :            : 
     615                 :      21540 :             xub_StrLen nOtherStart = *pOther->GetStart();
     616         [ +  - ]:      21540 :             const xub_StrLen nOtherEnd = *pOther->GetEnd();
     617                 :            : 
     618                 :            :             // Check if start of new attribute overlaps with pOther:
     619                 :            :             // Split pOther if necessary:
     620 [ +  + ][ +  + ]:      21540 :             if ( nOtherStart < nThisStart && nThisStart < nOtherEnd )
     621                 :            :             {
     622                 :         51 :                 SwTxtAttr* pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
     623         [ +  - ]:        102 :                         pOther->GetAttr(), nOtherStart, nThisStart );
     624 [ +  - ][ -  + ]:         51 :                 if ( RES_TXTATR_CHARFMT == pOther->Which() )
     625                 :          0 :                     static_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber( static_cast<SwTxtCharFmt*>(pOther)->GetSortNumber() );
     626         [ +  - ]:         51 :                 aInsDelHints.push_back( pNewAttr );
     627                 :            : 
     628         [ +  - ]:         51 :                 NoteInHistory( pOther );
     629                 :         51 :                 *pOther->GetStart() = nThisStart;
     630         [ +  - ]:         51 :                 NoteInHistory( pOther, true );
     631                 :            : 
     632                 :         51 :                 nOtherStart = nThisStart;
     633                 :            :             }
     634                 :            : 
     635                 :            :             // Check if end of new attribute overlaps with pOther:
     636                 :            :             // Split pOther if necessary:
     637 [ +  + ][ +  + ]:      21540 :             if ( nOtherStart < nThisEnd && nThisEnd < nOtherEnd )
     638                 :            :             {
     639                 :         48 :                 SwTxtAttr* pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
     640         [ +  - ]:         96 :                         pOther->GetAttr(), nOtherStart, nThisEnd );
     641 [ +  - ][ -  + ]:         48 :                 if ( RES_TXTATR_CHARFMT == pOther->Which() )
     642                 :          0 :                     static_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber( static_cast<SwTxtCharFmt*>(pOther)->GetSortNumber() );
     643         [ +  - ]:         48 :                 aInsDelHints.push_back( pNewAttr );
     644                 :            : 
     645         [ +  - ]:         48 :                 NoteInHistory( pOther );
     646                 :         48 :                 *pOther->GetStart() = nThisEnd;
     647         [ +  - ]:         48 :                 NoteInHistory( pOther, true );
     648                 :            :             }
     649                 :            :         }
     650                 :            : 
     651                 :            :         // Insert the newly created attributes:
     652 [ +  - ][ +  + ]:      13017 :         for ( aIter = aInsDelHints.begin(); aIter != aInsDelHints.end(); ++aIter )
     653                 :            :         {
     654         [ +  - ]:         99 :             SwpHintsArray::Insert( *aIter );
     655         [ +  - ]:         99 :             NoteInHistory( *aIter, true );
     656                 :            :         }
     657                 :            :     }
     658                 :            : 
     659                 :            : #ifdef DBG_UTIL
     660                 :            :     if( !rNode.GetDoc()->IsInReading() )
     661                 :            :         CHECK;
     662                 :            : #endif
     663                 :            : 
     664                 :            :     //
     665                 :            :     // 4. Split rNewHint into 1 ... n new hints:
     666                 :            :     //
     667         [ +  - ]:      14834 :     std::set<xub_StrLen> aBounds;
     668         [ +  - ]:      14834 :     aBounds.insert( nThisStart );
     669         [ +  - ]:      14834 :     aBounds.insert( nThisEnd );
     670                 :            : 
     671         [ +  + ]:      14834 :     if ( !bNoLengthAttribute ) // nothing to do for no length attributes
     672                 :            :     {
     673         [ +  + ]:      51677 :         for ( sal_uInt16 i = 0; i < Count(); ++i )
     674                 :            :         {
     675         [ +  - ]:      38759 :             const SwTxtAttr* pOther = GetTextHint(i);
     676                 :            : 
     677 [ +  - ][ +  + ]:      77449 :             if ( RES_TXTATR_CHARFMT != pOther->Which() &&
         [ +  + ][ +  + ]
     678         [ +  - ]:      38690 :                  RES_TXTATR_AUTOFMT != pOther->Which() )
     679                 :      17120 :                 continue;
     680                 :            : 
     681                 :      21639 :             const xub_StrLen nOtherStart = *pOther->GetStart();
     682         [ +  - ]:      21639 :             const xub_StrLen nOtherEnd = *pOther->GetEnd();
     683                 :            : 
     684         [ +  - ]:      21639 :             aBounds.insert( nOtherStart );
     685         [ +  - ]:      21639 :             aBounds.insert( nOtherEnd );
     686                 :            :         }
     687                 :            :     }
     688                 :            : 
     689         [ +  - ]:      14834 :     std::set<xub_StrLen>::iterator aStartIter = aBounds.lower_bound( nThisStart );
     690         [ +  - ]:      14834 :     std::set<xub_StrLen>::iterator aEndIter = aBounds.upper_bound( nThisEnd );
     691         [ +  - ]:      14834 :     xub_StrLen nPorStart = *aStartIter;
     692         [ +  - ]:      14834 :     ++aStartIter;
     693                 :      14834 :     bool bDestroyHint = true;
     694                 :            : 
     695                 :            :     //
     696                 :            :     // Insert the 1...n new parts of the new attribute:
     697                 :            :     //
     698 [ +  - ][ +  + ]:      27806 :     while ( aStartIter != aEndIter || bNoLengthAttribute )
         [ +  + ][ +  + ]
     699                 :            :     {
     700                 :            :         OSL_ENSURE( bNoLengthAttribute || nPorStart < *aStartIter, "AUTOSTYLES: BuildPortion trouble" );
     701                 :            : 
     702 [ +  + ][ +  - ]:      14888 :         const xub_StrLen nPorEnd = bNoLengthAttribute ? nPorStart : *aStartIter;
     703                 :      14888 :         aInsDelHints.clear();
     704                 :            : 
     705                 :            :         // Get all hints that are in [nPorStart, nPorEnd[:
     706         [ +  + ]:      58155 :         for ( sal_uInt16 i = 0; i < Count(); ++i )
     707                 :            :         {
     708         [ +  - ]:      43471 :             SwTxtAttr *pOther = GetTextHint(i);
     709                 :            : 
     710 [ +  - ][ +  + ]:      86873 :             if ( RES_TXTATR_CHARFMT != pOther->Which() &&
         [ +  + ][ +  + ]
     711         [ +  - ]:      43402 :                  RES_TXTATR_AUTOFMT != pOther->Which() )
     712                 :      19847 :                 continue;
     713                 :            : 
     714                 :      23624 :             const xub_StrLen nOtherStart = *pOther->GetStart();
     715                 :            : 
     716         [ +  + ]:      23624 :             if ( nOtherStart > nPorStart )
     717                 :            :                 break;
     718                 :            : 
     719 [ +  - ][ +  - ]:      23420 :             if ( pOther->GetEnd() && *pOther->GetEnd() == nPorEnd && nOtherStart == nPorStart )
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
     720                 :            :             {
     721                 :            :                 OSL_ENSURE( *pOther->GetEnd() == nPorEnd, "AUTOSTYLES: BuildPortion trouble" );
     722         [ +  - ]:      23624 :                 aInsDelHints.push_back( pOther );
     723                 :            :             }
     724                 :            :         }
     725                 :            : 
     726                 :      14888 :         SwTxtAttr* pNewAttr = 0;
     727         [ +  + ]:      14888 :         if ( RES_TXTATR_CHARFMT == nWhich )
     728                 :            :         {
     729                 :            :             // pNewHint can be inserted after calculating the sort value.
     730                 :            :             // This should ensure, that pNewHint comes behind the already present
     731                 :            :             // character style
     732                 :         43 :             sal_uInt16 nCharStyleCount = 0;
     733                 :         43 :             aIter = aInsDelHints.begin();
     734 [ +  - ][ +  + ]:         47 :             while ( aIter != aInsDelHints.end() )
     735                 :            :             {
     736 [ +  - ][ -  + ]:          4 :                 if ( RES_TXTATR_CHARFMT == (*aIter)->Which() )
     737                 :            :                 {
     738                 :            :                     // #i74589#
     739                 :          0 :                     const SwFmtCharFmt& rOtherCharFmt = (*aIter)->GetCharFmt();
     740                 :          0 :                     const SwFmtCharFmt& rThisCharFmt = rNewHint.GetCharFmt();
     741                 :          0 :                     const bool bSameCharFmt = rOtherCharFmt.GetCharFmt() == rThisCharFmt.GetCharFmt();
     742                 :            : 
     743                 :            :                     // #i90311#
     744                 :            :                     // Do not remove existing character format hint during XML import
     745 [ #  # ][ #  # ]:          0 :                     if ( !rNode.GetDoc()->IsInXMLImport() &&
         [ #  # ][ #  # ]
                 [ #  # ]
     746                 :          0 :                          ( !( nsSetAttrMode::SETATTR_DONTREPLACE & nMode ) ||
     747                 :            :                            bNoLengthAttribute ||
     748                 :            :                            bSameCharFmt ) )
     749                 :            :                     {
     750                 :            :                         // Remove old hint
     751         [ #  # ]:          0 :                         Delete( *aIter );
     752         [ #  # ]:          0 :                         rNode.DestroyAttr( *aIter );
     753                 :            :                     }
     754                 :            :                     else
     755                 :          0 :                         ++nCharStyleCount;
     756                 :            :                 }
     757                 :            :                 else
     758                 :            :                 {
     759                 :            :                     // remove all attributes from auto styles, which are explicitly set in
     760                 :            :                     // the new character format:
     761                 :            :                     OSL_ENSURE( RES_TXTATR_AUTOFMT == (*aIter)->Which(), "AUTOSTYLES - Misc trouble" );
     762                 :          4 :                     SwTxtAttr* pOther = *aIter;
     763         [ +  - ]:          4 :                     boost::shared_ptr<SfxItemSet> pOldStyle = static_cast<const SwFmtAutoFmt&>(pOther->GetAttr()).GetStyleHandle();
     764                 :            : 
     765                 :            :                     // For each attribute in the automatic style check if it
     766                 :            :                     // is also set the the new character style:
     767                 :          4 :                     SfxItemSet aNewSet( *pOldStyle->GetPool(),
     768         [ +  - ]:          4 :                         aCharAutoFmtSetRange);
     769         [ +  - ]:          4 :                     SfxItemIter aItemIter( *pOldStyle );
     770                 :          4 :                     const SfxPoolItem* pItem = aItemIter.GetCurItem();
     771                 :         32 :                     while( sal_True )
     772                 :            :                     {
     773 [ +  - ][ +  - ]:         36 :                         if ( !CharFmt::IsItemIncluded( pItem->Which(), &rNewHint ) )
     774                 :            :                         {
     775         [ +  - ]:         36 :                             aNewSet.Put( *pItem );
     776                 :            :                         }
     777                 :            : 
     778         [ +  + ]:         36 :                         if( aItemIter.IsAtEnd() )
     779                 :          4 :                             break;
     780                 :            : 
     781         [ +  - ]:         32 :                         pItem = aItemIter.NextItem();
     782                 :            :                     }
     783                 :            : 
     784                 :            :                     // Remove old hint
     785         [ +  - ]:          4 :                     Delete( pOther );
     786         [ +  - ]:          4 :                     rNode.DestroyAttr( pOther );
     787                 :            : 
     788                 :            :                     // Create new AutoStyle
     789         [ +  - ]:          4 :                     if ( aNewSet.Count() )
     790                 :            :                     {
     791                 :          4 :                         pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
     792         [ +  - ]:          4 :                                 aNewSet, nPorStart, nPorEnd );
     793         [ +  - ]:          4 :                         SwpHintsArray::Insert( pNewAttr );
     794         [ +  - ]:          4 :                         NoteInHistory( pNewAttr, true );
     795 [ +  - ][ +  - ]:          4 :                     }
                 [ +  - ]
     796                 :            :                 }
     797                 :          4 :                 ++aIter;
     798                 :            :             }
     799                 :            : 
     800                 :            :             // If there is no current hint and start and end of rNewHint
     801                 :            :             // is ok, we do not need to create a new txtattr.
     802 [ +  - ][ +  - ]:         43 :             if ( nPorStart == nThisStart &&
                 [ +  - ]
     803                 :            :                  nPorEnd == nThisEnd &&
     804                 :            :                  !nCharStyleCount )
     805                 :            :             {
     806                 :         43 :                 pNewAttr = &rNewHint;
     807                 :         43 :                 bDestroyHint = false;
     808                 :            :             }
     809                 :            :             else
     810                 :            :             {
     811                 :          0 :                 pNewAttr = MakeTxtAttr( *rNode.GetDoc(), rNewHint.GetAttr(),
     812         [ #  # ]:          0 :                         nPorStart, nPorEnd );
     813                 :         43 :                 static_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber( nCharStyleCount );
     814                 :            :             }
     815                 :            :         }
     816                 :            :         else
     817                 :            :         {
     818                 :            :             // Find the current autostyle. Mix attributes if necessary.
     819                 :      14845 :             SwTxtAttr* pCurrentAutoStyle = 0;
     820                 :      14845 :             SwTxtAttr* pCurrentCharFmt = 0;
     821                 :      14845 :             aIter = aInsDelHints.begin();
     822 [ +  - ][ +  + ]:      25790 :             while ( aIter != aInsDelHints.end() )
     823                 :            :             {
     824 [ +  - ][ +  + ]:      10945 :                 if ( RES_TXTATR_AUTOFMT == (*aIter)->Which() )
     825                 :      10876 :                     pCurrentAutoStyle = *aIter;
     826 [ +  - ][ +  - ]:         69 :                 else if ( RES_TXTATR_CHARFMT == (*aIter)->Which() )
     827                 :         69 :                     pCurrentCharFmt = *aIter;
     828                 :      10945 :                 ++aIter;
     829                 :            :             }
     830                 :            : 
     831         [ +  - ]:      14845 :             boost::shared_ptr<SfxItemSet> pNewStyle = static_cast<const SwFmtAutoFmt&>(rNewHint.GetAttr()).GetStyleHandle();
     832         [ +  + ]:      14845 :             if ( pCurrentAutoStyle )
     833                 :            :             {
     834         [ +  - ]:      10876 :                 boost::shared_ptr<SfxItemSet> pCurrentStyle = static_cast<const SwFmtAutoFmt&>(pCurrentAutoStyle->GetAttr()).GetStyleHandle();
     835                 :            : 
     836                 :            :                 // Merge attributes
     837         [ +  - ]:      10876 :                 SfxItemSet aNewSet( *pCurrentStyle );
     838         [ +  - ]:      10876 :                 aNewSet.Put( *pNewStyle );
     839                 :            : 
     840                 :            :                 // #i75750# Remove attributes already set at whole paragraph
     841                 :            :                 // #i81764# This should not be applied for no length attributes!!! <--
     842 [ +  + ][ +  - ]:      10876 :                 if ( !bNoLengthAttribute && rNode.HasSwAttrSet() && aNewSet.Count() )
         [ +  + ][ +  - ]
                 [ +  + ]
     843                 :            :                 {
     844         [ +  - ]:       1976 :                     SfxItemIter aIter2( aNewSet );
     845                 :       1976 :                     const SfxPoolItem* pItem = aIter2.GetCurItem();
     846         [ +  - ]:       1976 :                     const SfxItemSet& rWholeParaAttrSet = rNode.GetSwAttrSet();
     847                 :            : 
     848 [ +  - ][ +  - ]:       4745 :                     do
         [ +  + ][ +  + ]
     849                 :            :                     {
     850                 :       4745 :                         const SfxPoolItem* pTmpItem = 0;
     851 [ +  - ][ +  + ]:       4745 :                         if ( SFX_ITEM_SET == rWholeParaAttrSet.GetItemState( pItem->Which(), sal_False, &pTmpItem ) &&
         [ -  + ][ -  + ]
     852                 :            :                              pTmpItem == pItem )
     853                 :            :                         {
     854                 :            :                             // Do not clear item if the attribute is set in a character format:
     855 [ #  # ][ #  # ]:          0 :                             if ( !pCurrentCharFmt || 0 == CharFmt::GetItem( *pCurrentCharFmt, pItem->Which() ) )
         [ #  # ][ #  # ]
     856         [ #  # ]:          0 :                                 aNewSet.ClearItem( pItem->Which() );
     857                 :            :                         }
     858                 :            :                     }
     859         [ +  - ]:       6721 :                     while (!aIter2.IsAtEnd() && 0 != (pItem = aIter2.NextItem()));
     860                 :            :                 }
     861                 :            : 
     862                 :            :                 // Remove old hint
     863         [ +  - ]:      10876 :                 Delete( pCurrentAutoStyle );
     864         [ +  - ]:      10876 :                 rNode.DestroyAttr( pCurrentAutoStyle );
     865                 :            : 
     866                 :            :                 // Create new AutoStyle
     867         [ +  - ]:      10876 :                 if ( aNewSet.Count() )
     868                 :      10876 :                     pNewAttr = MakeTxtAttr( *rNode.GetDoc(), aNewSet,
     869 [ +  - ][ +  - ]:      10876 :                             nPorStart, nPorEnd );
                 [ +  - ]
     870                 :            :             }
     871                 :            :             else
     872                 :            :             {
     873                 :            :                 // Remove any attributes which are already set at the whole paragraph:
     874                 :       3969 :                 bool bOptimizeAllowed = true;
     875                 :            : 
     876                 :       3969 :                 SfxItemSet* pNewSet = 0;
     877                 :            :                 // #i75750# Remove attributes already set at whole paragraph
     878                 :            :                 // #i81764# This should not be applied for no length attributes!!! <--
     879 [ +  + ][ +  - ]:       3969 :                 if ( !bNoLengthAttribute && rNode.HasSwAttrSet() && pNewStyle->Count() )
         [ +  + ][ +  - ]
                 [ +  + ]
     880                 :            :                 {
     881         [ +  - ]:       2275 :                     SfxItemIter aIter2( *pNewStyle );
     882                 :       2275 :                     const SfxPoolItem* pItem = aIter2.GetCurItem();
     883         [ +  - ]:       2275 :                     const SfxItemSet& rWholeParaAttrSet = rNode.GetSwAttrSet();
     884                 :            : 
     885 [ +  - ][ +  - ]:       2422 :                     do
         [ +  + ][ +  + ]
     886                 :            :                     {
     887                 :       2422 :                         const SfxPoolItem* pTmpItem = 0;
     888 [ +  - ][ -  + ]:       2422 :                         if ( SFX_ITEM_SET == rWholeParaAttrSet.GetItemState( pItem->Which(), sal_False, &pTmpItem ) &&
         [ #  # ][ -  + ]
     889                 :            :                              pTmpItem == pItem )
     890                 :            :                         {
     891                 :            :                             // Do not clear item if the attribute is set in a character format:
     892 [ #  # ][ #  # ]:          0 :                             if ( !pCurrentCharFmt || 0 == CharFmt::GetItem( *pCurrentCharFmt, pItem->Which() ) )
         [ #  # ][ #  # ]
     893                 :            :                             {
     894         [ #  # ]:          0 :                                 if ( !pNewSet )
     895         [ #  # ]:          0 :                                     pNewSet = pNewStyle->Clone( sal_True );
     896         [ #  # ]:          0 :                                 pNewSet->ClearItem( pItem->Which() );
     897                 :            :                             }
     898                 :            :                         }
     899                 :            :                     }
     900                 :       2422 :                     while (!aIter2.IsAtEnd() && 0 != (pItem = aIter2.NextItem()));
     901                 :            : 
     902         [ -  + ]:       2275 :                     if ( pNewSet )
     903                 :            :                     {
     904                 :          0 :                         bOptimizeAllowed = false;
     905         [ #  # ]:          0 :                         if ( pNewSet->Count() )
     906 [ #  # ][ #  # ]:          0 :                             pNewStyle = rNode.getIDocumentStyleAccess().getAutomaticStyle( *pNewSet, IStyleAccess::AUTO_STYLE_CHAR );
         [ #  # ][ #  # ]
     907                 :            :                         else
     908         [ #  # ]:          0 :                             pNewStyle.reset();
     909                 :            : 
     910 [ #  # ][ #  # ]:          0 :                         delete pNewSet;
     911         [ +  - ]:       2275 :                     }
     912                 :            :                 }
     913                 :            : 
     914                 :            :                 // Create new AutoStyle
     915                 :            :                 // If there is no current hint and start and end of rNewHint
     916                 :            :                 // is ok, we do not need to create a new txtattr.
     917 [ +  - ][ +  + ]:       3969 :                 if ( bOptimizeAllowed &&
                 [ +  - ]
     918                 :            :                      nPorStart == nThisStart &&
     919                 :            :                      nPorEnd == nThisEnd )
     920                 :            :                 {
     921                 :       3939 :                     pNewAttr = &rNewHint;
     922                 :       3939 :                     bDestroyHint = false;
     923                 :            :                 }
     924         [ +  - ]:         30 :                 else if ( pNewStyle.get() )
     925                 :            :                 {
     926                 :         30 :                     pNewAttr = MakeTxtAttr( *rNode.GetDoc(), *pNewStyle,
     927         [ +  - ]:         30 :                             nPorStart, nPorEnd );
     928                 :            :                 }
     929         [ +  - ]:      14845 :             }
     930                 :            :         }
     931                 :            : 
     932         [ +  - ]:      14888 :         if ( pNewAttr )
     933                 :            :         {
     934         [ +  - ]:      14888 :             SwpHintsArray::Insert( pNewAttr );
     935                 :            : //            if ( bDestroyHint )
     936         [ +  - ]:      14888 :                 NoteInHistory( pNewAttr, true );
     937                 :            :         }
     938                 :            : 
     939         [ +  + ]:      14888 :         if ( !bNoLengthAttribute )
     940                 :            :         {
     941         [ +  - ]:      12972 :             nPorStart = *aStartIter;
     942         [ +  - ]:      12972 :             ++aStartIter;
     943                 :            :         }
     944                 :            :         else
     945                 :       1916 :             break;
     946                 :            :     }
     947                 :            : 
     948         [ +  + ]:      14834 :     if ( bDestroyHint )
     949         [ +  - ]:      14834 :         rNode.DestroyAttr( &rNewHint );
     950                 :      14834 : }
     951                 :            : 
     952                 :            : /*************************************************************************
     953                 :            :  *                      SwTxtNode::MakeTxtAttr()
     954                 :            :  *************************************************************************/
     955                 :            : 
     956                 :          0 : SwTxtAttr* MakeRedlineTxtAttr( SwDoc & rDoc, SfxPoolItem & rAttr )
     957                 :            : {
     958                 :            :     // this is intended _only_ for special-purpose redline attributes!
     959         [ #  # ]:          0 :     switch (rAttr.Which())
     960                 :            :     {
     961                 :            :         case RES_CHRATR_COLOR:
     962                 :            :         case RES_CHRATR_WEIGHT:
     963                 :            :         case RES_CHRATR_CJK_WEIGHT:
     964                 :            :         case RES_CHRATR_CTL_WEIGHT:
     965                 :            :         case RES_CHRATR_POSTURE:
     966                 :            :         case RES_CHRATR_CJK_POSTURE:
     967                 :            :         case RES_CHRATR_CTL_POSTURE:
     968                 :            :         case RES_CHRATR_UNDERLINE:
     969                 :            :         case RES_CHRATR_CROSSEDOUT:
     970                 :            :         case RES_CHRATR_CASEMAP:
     971                 :            :         case RES_CHRATR_BACKGROUND:
     972                 :          0 :             break;
     973                 :            :         default:
     974                 :            :             OSL_FAIL("unsupported redline attribute");
     975                 :          0 :             break;
     976                 :            :     }
     977                 :            : 
     978                 :            :     // Put new attribute into pool
     979                 :            :     // FIXME: this const_cast is evil!
     980                 :            :     SfxPoolItem& rNew =
     981                 :          0 :         const_cast<SfxPoolItem&>( rDoc.GetAttrPool().Put( rAttr ) );
     982         [ #  # ]:          0 :     return new SwTxtAttrEnd( rNew, 0, 0 );
     983                 :            : }
     984                 :            : 
     985                 :            : // create new text attribute
     986                 :      30711 : SwTxtAttr* MakeTxtAttr( SwDoc & rDoc, SfxPoolItem& rAttr,
     987                 :            :         xub_StrLen const nStt, xub_StrLen const nEnd,
     988                 :            :         CopyOrNew_t const bIsCopy, SwTxtNode *const pTxtNode)
     989                 :            : {
     990         [ +  + ]:      30711 :     if ( isCHRATR(rAttr.Which()) )
     991                 :            :     {
     992                 :            :         // Somebody wants to build a SwTxtAttr for a character attribute.
     993                 :            :         // Sorry, this is not allowed any longer.
     994                 :            :         // You'll get a brand new autostyle attribute:
     995                 :        841 :         SfxItemSet aItemSet( rDoc.GetAttrPool(),
     996         [ +  - ]:        841 :                 RES_CHRATR_BEGIN, RES_CHRATR_END );
     997         [ +  - ]:        841 :         aItemSet.Put( rAttr );
     998 [ +  - ][ +  - ]:        841 :         return MakeTxtAttr( rDoc, aItemSet, nStt, nEnd );
     999                 :            :     }
    1000   [ +  +  -  + ]:      86122 :     else if ( RES_TXTATR_AUTOFMT == rAttr.Which() &&
                 [ -  + ]
    1001                 :            :               static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle()->
    1002 [ +  - ][ +  + ]:      56252 :                 GetPool() != &rDoc.GetAttrPool() )
                 [ #  # ]
    1003                 :            :     {
    1004                 :            :         // If the attribute is an auto-style which refers to a pool that is
    1005                 :            :         // different from rDoc's pool, we have to correct this:
    1006         [ #  # ]:          0 :         const StylePool::SfxItemSet_Pointer_t pAutoStyle = static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle();
    1007                 :            :         ::std::auto_ptr<const SfxItemSet> pNewSet(
    1008         [ #  # ]:          0 :                 pAutoStyle->SfxItemSet::Clone( sal_True, &rDoc.GetAttrPool() ));
    1009         [ #  # ]:          0 :         SwTxtAttr* pNew = MakeTxtAttr( rDoc, *pNewSet, nStt, nEnd );
    1010 [ #  # ][ #  # ]:          0 :         return pNew;
    1011                 :            :     }
    1012                 :            : 
    1013                 :            :     // Put new attribute into pool
    1014                 :            :     // FIXME: this const_cast is evil!
    1015                 :            :     SfxPoolItem& rNew =
    1016                 :      29870 :         const_cast<SfxPoolItem&>( rDoc.GetAttrPool().Put( rAttr ) );
    1017                 :            : 
    1018                 :      29870 :     SwTxtAttr* pNew = 0;
    1019   [ +  +  +  +  :      29870 :     switch( rNew.Which() )
          +  +  +  +  +  
                      + ]
    1020                 :            :     {
    1021                 :            :     case RES_TXTATR_CHARFMT:
    1022                 :            :         {
    1023                 :         43 :             SwFmtCharFmt &rFmtCharFmt = (SwFmtCharFmt&) rNew;
    1024         [ -  + ]:         43 :             if( !rFmtCharFmt.GetCharFmt() )
    1025                 :            :             {
    1026                 :          0 :                 rFmtCharFmt.SetCharFmt( rDoc.GetDfltCharFmt() );
    1027                 :            :             }
    1028                 :            : 
    1029         [ +  - ]:         43 :             pNew = new SwTxtCharFmt( rFmtCharFmt, nStt, nEnd );
    1030                 :            :         }
    1031                 :         43 :         break;
    1032                 :            :     case RES_TXTATR_INETFMT:
    1033         [ +  - ]:        115 :         pNew = new SwTxtINetFmt( (SwFmtINetFmt&)rNew, nStt, nEnd );
    1034                 :        115 :         break;
    1035                 :            :     case RES_TXTATR_FIELD:
    1036                 :            :         pNew = new SwTxtFld( static_cast<SwFmtFld &>(rNew), nStt,
    1037         [ +  - ]:       1549 :                     rDoc.IsClipBoard() );
    1038                 :       1549 :         break;
    1039                 :            :     case RES_TXTATR_FLYCNT:
    1040                 :            :         {
    1041                 :            :             // erst hier wird das Frame-Format kopiert (mit Inhalt) !!
    1042         [ +  - ]:        970 :             pNew = new SwTxtFlyCnt( (SwFmtFlyCnt&)rNew, nStt );
    1043                 :            :             // Kopie von einem Text-Attribut
    1044         [ +  + ]:        970 :             if ( static_cast<const SwFmtFlyCnt &>(rAttr).GetTxtFlyCnt() )
    1045                 :            :             {
    1046                 :            :                 // then the format must be copied
    1047                 :          3 :                 static_cast<SwTxtFlyCnt *>(pNew)->CopyFlyFmt( &rDoc );
    1048                 :            :             }
    1049                 :            :         }
    1050                 :        970 :         break;
    1051                 :            :     case RES_TXTATR_FTN:
    1052         [ +  - ]:         72 :         pNew = new SwTxtFtn( (SwFmtFtn&)rNew, nStt );
    1053                 :            :         // ggfs. SeqNo kopieren
    1054         [ -  + ]:         72 :         if( ((SwFmtFtn&)rAttr).GetTxtFtn() )
    1055                 :          0 :             ((SwTxtFtn*)pNew)->SetSeqNo( ((SwFmtFtn&)rAttr).GetTxtFtn()->GetSeqRefNo() );
    1056                 :         72 :         break;
    1057                 :            :     case RES_TXTATR_REFMARK:
    1058                 :            :         pNew = nStt == nEnd
    1059         [ +  - ]:         55 :                 ? new SwTxtRefMark( (SwFmtRefMark&)rNew, nStt )
    1060 [ +  + ][ +  - ]:        138 :                 : new SwTxtRefMark( (SwFmtRefMark&)rNew, nStt, &nEnd );
    1061                 :         83 :         break;
    1062                 :            :     case RES_TXTATR_TOXMARK:
    1063         [ +  - ]:         78 :         pNew = new SwTxtTOXMark( (SwTOXMark&)rNew, nStt, &nEnd );
    1064                 :         78 :         break;
    1065                 :            :     case RES_TXTATR_CJK_RUBY:
    1066         [ +  - ]:        384 :         pNew = new SwTxtRuby( (SwFmtRuby&)rNew, nStt, nEnd );
    1067                 :        384 :         break;
    1068                 :            :     case RES_TXTATR_META:
    1069                 :            :     case RES_TXTATR_METAFIELD:
    1070                 :        194 :         pNew = SwTxtMeta::CreateTxtMeta( rDoc.GetMetaFieldManager(), pTxtNode,
    1071                 :        194 :                 static_cast<SwFmtMeta&>(rNew), nStt, nEnd, bIsCopy );
    1072                 :        194 :         break;
    1073                 :            :     default:
    1074                 :            :         OSL_ENSURE(RES_TXTATR_AUTOFMT == rNew.Which(), "unknown attribute");
    1075         [ +  - ]:      26382 :         pNew = new SwTxtAttrEnd( rNew, nStt, nEnd );
    1076                 :      26382 :         break;
    1077                 :            :     }
    1078                 :            : 
    1079                 :      30711 :     return pNew;
    1080                 :            : }
    1081                 :            : 
    1082                 :      25433 : SwTxtAttr* MakeTxtAttr( SwDoc & rDoc, const SfxItemSet& rSet,
    1083                 :            :                         xub_StrLen nStt, xub_StrLen nEnd )
    1084                 :            : {
    1085                 :      25433 :     IStyleAccess& rStyleAccess = rDoc.GetIStyleAccess();
    1086         [ +  - ]:      25433 :     const StylePool::SfxItemSet_Pointer_t pAutoStyle = rStyleAccess.getAutomaticStyle( rSet, IStyleAccess::AUTO_STYLE_CHAR );
    1087         [ +  - ]:      25433 :     SwFmtAutoFmt aNewAutoFmt;
    1088 [ +  - ][ +  - ]:      25433 :     aNewAutoFmt.SetStyleHandle( pAutoStyle );
                 [ +  - ]
    1089         [ +  - ]:      25433 :     SwTxtAttr* pNew = MakeTxtAttr( rDoc, aNewAutoFmt, nStt, nEnd );
    1090 [ +  - ][ +  - ]:      25433 :     return pNew;
    1091                 :            : }
    1092                 :            : 
    1093                 :            : 
    1094                 :            : // loesche das Text-Attribut (muss beim Pool abgemeldet werden!)
    1095                 :      29767 : void SwTxtNode::DestroyAttr( SwTxtAttr* pAttr )
    1096                 :            : {
    1097         [ +  - ]:      29767 :     if( pAttr )
    1098                 :            :     {
    1099                 :            :         // einige Sachen muessen vorm Loeschen der "Format-Attribute" erfolgen
    1100                 :      29767 :         SwDoc* pDoc = GetDoc();
    1101                 :      29767 :         sal_uInt16 nDelMsg = 0;
    1102   [ +  -  +  +  :      29767 :         switch( pAttr->Which() )
             +  +  +  + ]
    1103                 :            :         {
    1104                 :            :         case RES_TXTATR_FLYCNT:
    1105                 :            :             {
    1106                 :            :                 // siehe auch die Anmerkung "Loeschen von Formaten
    1107                 :            :                 // zeichengebundener Frames" in fesh.cxx, SwFEShell::DelFmt()
    1108                 :        883 :                 SwFrmFmt* pFmt = pAttr->GetFlyCnt().GetFrmFmt();
    1109         [ +  + ]:        883 :                 if( pFmt )      // vom Undo auf 0 gesetzt ??
    1110                 :        869 :                     pDoc->DelLayoutFmt( (SwFlyFrmFmt*)pFmt );
    1111                 :            :             }
    1112                 :        883 :             break;
    1113                 :            : 
    1114                 :            :         case RES_CHRATR_HIDDEN:
    1115                 :          0 :             SetCalcHiddenCharFlags();
    1116                 :          0 :             break;
    1117                 :            : 
    1118                 :            :         case RES_TXTATR_FTN:
    1119                 :         69 :             ((SwTxtFtn*)pAttr)->SetStartNode( 0 );
    1120                 :         69 :             nDelMsg = RES_FOOTNOTE_DELETED;
    1121                 :         69 :             break;
    1122                 :            : 
    1123                 :            :         case RES_TXTATR_FIELD:
    1124         [ +  + ]:       1546 :             if( !pDoc->IsInDtor() )
    1125                 :            :             {
    1126                 :            :                 // Wenn wir ein HiddenParaField sind, dann muessen wir
    1127                 :            :                 // ggf. fuer eine Neuberechnung des Visible-Flags sorgen.
    1128                 :         38 :                 const SwField* pFld = pAttr->GetFld().GetFld();
    1129                 :            : 
    1130                 :            :                 //JP 06-08-95: DDE-Felder bilden eine Ausnahme
    1131                 :            :                 OSL_ENSURE( RES_DDEFLD == pFld->GetTyp()->Which() ||
    1132                 :            :                         this == ((SwTxtFld*)pAttr)->GetpTxtNode(),
    1133                 :            :                         "Wo steht denn dieses Feld?" );
    1134                 :            : 
    1135                 :            :                 // bestimmte Felder mussen am Doc das Calculations-Flag updaten
    1136   [ -  +  -  +  :         38 :                 switch( pFld->GetTyp()->Which() )
                      + ]
    1137                 :            :                 {
    1138                 :            :                 case RES_HIDDENPARAFLD:
    1139                 :          0 :                     SetCalcHiddenParaField();
    1140                 :            :                     // kein break !
    1141                 :            :                 case RES_DBSETNUMBERFLD:
    1142                 :            :                 case RES_GETEXPFLD:
    1143                 :            :                 case RES_DBFLD:
    1144                 :            :                 case RES_SETEXPFLD:
    1145                 :            :                 case RES_HIDDENTXTFLD:
    1146                 :            :                 case RES_DBNUMSETFLD:
    1147                 :            :                 case RES_DBNEXTSETFLD:
    1148 [ -  + ][ #  # ]:          2 :                     if( !pDoc->IsNewFldLst() && GetNodes().IsDocNodes() )
                 [ -  + ]
    1149                 :          0 :                         pDoc->InsDelFldInFldLst( sal_False, *(SwTxtFld*)pAttr );
    1150                 :          2 :                     break;
    1151                 :            :                 case RES_DDEFLD:
    1152   [ #  #  #  # ]:          0 :                     if( GetNodes().IsDocNodes() &&
                 [ #  # ]
    1153                 :          0 :                         ((SwTxtFld*)pAttr)->GetpTxtNode() )
    1154                 :          0 :                         ((SwDDEFieldType*)pFld->GetTyp())->DecRefCnt();
    1155                 :          0 :                     break;
    1156                 :            :                 case RES_POSTITFLD:
    1157                 :            :                     {
    1158         [ +  - ]:          6 :                         const_cast<SwFmtFld&>(pAttr->GetFld()).Broadcast( SwFmtFldHint( &((SwTxtFld*)pAttr)->GetFld(), SWFMTFLD_REMOVED ) );
    1159                 :         38 :                         break;
    1160                 :            :                     }
    1161                 :            :                 }
    1162                 :            :             }
    1163                 :       1546 :             nDelMsg = RES_FIELD_DELETED;
    1164                 :       1546 :             break;
    1165                 :            : 
    1166                 :            :         case RES_TXTATR_TOXMARK:
    1167                 :         78 :             static_cast<SwTOXMark&>(pAttr->GetAttr()).InvalidateTOXMark();
    1168                 :         78 :             break;
    1169                 :            : 
    1170                 :            :         case RES_TXTATR_REFMARK:
    1171                 :         83 :             nDelMsg = RES_REFMARK_DELETED;
    1172                 :         83 :             break;
    1173                 :            : 
    1174                 :            :         case RES_TXTATR_META:
    1175                 :            :         case RES_TXTATR_METAFIELD:
    1176                 :        190 :             static_cast<SwTxtMeta*>(pAttr)->ChgTxtNode(0);
    1177                 :        190 :             break;
    1178                 :            : 
    1179                 :            :         default:
    1180                 :      26918 :             break;
    1181                 :            :         }
    1182                 :            : 
    1183 [ +  + ][ +  + ]:      29767 :         if( nDelMsg && !pDoc->IsInDtor() && GetNodes().IsDocNodes() )
         [ +  - ][ +  + ]
    1184                 :            :         {
    1185         [ +  - ]:         86 :             SwPtrMsgPoolItem aMsgHint( nDelMsg, (void*)&pAttr->GetAttr() );
    1186 [ +  - ][ +  - ]:         86 :             pDoc->GetUnoCallBack()->ModifyNotification( &aMsgHint, &aMsgHint );
                 [ +  - ]
    1187                 :            :         }
    1188                 :            : 
    1189                 :      29767 :         SwTxtAttr::Destroy( pAttr, pDoc->GetAttrPool() );
    1190                 :            :     }
    1191                 :      29767 : }
    1192                 :            : 
    1193                 :            : /*************************************************************************
    1194                 :            :  *                      SwTxtNode::Insert()
    1195                 :            :  *************************************************************************/
    1196                 :            : 
    1197                 :            : SwTxtAttr*
    1198                 :       1039 : SwTxtNode::InsertItem( SfxPoolItem& rAttr,
    1199                 :            :       const xub_StrLen nStart, const xub_StrLen nEnd, const SetAttrMode nMode )
    1200                 :            : {
    1201                 :            :    // character attributes will be inserted as automatic styles:
    1202                 :            :     OSL_ENSURE( !isCHRATR(rAttr.Which()), "AUTOSTYLES - "
    1203                 :            :         "SwTxtNode::InsertItem should not be called with character attributes");
    1204                 :            : 
    1205                 :       1039 :     SwTxtAttr *const pNew = MakeTxtAttr( *GetDoc(), rAttr, nStart, nEnd,
    1206         [ +  + ]:       2078 :             (nMode & nsSetAttrMode::SETATTR_IS_COPY) ? COPY : NEW, this );
    1207                 :            : 
    1208         [ +  - ]:       1039 :     if ( pNew )
    1209                 :            :     {
    1210                 :       1039 :         const bool bSuccess( InsertHint( pNew, nMode ) );
    1211                 :            :         // N.B.: also check that the hint is actually in the hints array,
    1212                 :            :         // because hints of certain types may be merged after successful
    1213                 :            :         // insertion, and thus destroyed!
    1214 [ +  + ][ +  + ]:       1039 :         if (!bSuccess || ( USHRT_MAX == m_pSwpHints->GetPos( pNew ) ))
                 [ +  - ]
    1215                 :            :         {
    1216                 :          3 :             return 0;
    1217                 :            :         }
    1218                 :            :     }
    1219                 :            : 
    1220                 :       1039 :     return pNew;
    1221                 :            : }
    1222                 :            : 
    1223                 :            : // take ownership of pAttr; if insertion fails, delete pAttr
    1224                 :      19573 : bool SwTxtNode::InsertHint( SwTxtAttr * const pAttr, const SetAttrMode nMode )
    1225                 :            : {
    1226                 :      19573 :     sal_Bool bHiddenPara = sal_False;
    1227                 :            : 
    1228                 :            :     OSL_ENSURE( pAttr && *pAttr->GetStart() <= Len(), "StartIdx out of bounds!" );
    1229                 :            :     OSL_ENSURE( !pAttr->GetEnd() || (*pAttr->GetEnd() <= Len()),
    1230                 :            :             "EndIdx out of bounds!" );
    1231                 :            : 
    1232                 :            :     // translate from SetAttrMode to InsertMode (for hints with CH_TXTATR)
    1233                 :            :     const enum IDocumentContentOperations::InsertFlags nInsertFlags =
    1234                 :            :         (nMode & nsSetAttrMode::SETATTR_FORCEHINTEXPAND)
    1235                 :            :         ? static_cast<IDocumentContentOperations::InsertFlags>(
    1236                 :            :                 IDocumentContentOperations::INS_FORCEHINTEXPAND |
    1237                 :            :                 IDocumentContentOperations::INS_EMPTYEXPAND)
    1238         [ +  + ]:      19573 :         : IDocumentContentOperations::INS_EMPTYEXPAND;
    1239                 :            : 
    1240                 :            :     // need this after TryInsertHint, when pAttr may be deleted
    1241                 :      19573 :     const xub_StrLen nStart( *pAttr->GetStart() );
    1242                 :      19573 :     const bool bDummyChar( pAttr->HasDummyChar() );
    1243         [ +  + ]:      19573 :     if (bDummyChar)
    1244                 :            :     {
    1245                 :       2890 :         sal_uInt16 nInsMode = nMode;
    1246   [ +  +  +  + ]:       2890 :         switch( pAttr->Which() )
    1247                 :            :         {
    1248                 :            :             case RES_TXTATR_FLYCNT:
    1249                 :            :             {
    1250                 :        970 :                 SwTxtFlyCnt *pFly = (SwTxtFlyCnt *)pAttr;
    1251                 :        970 :                 SwFrmFmt* pFmt = pAttr->GetFlyCnt().GetFrmFmt();
    1252         [ +  + ]:        970 :                 if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
    1253                 :            :                 {
    1254                 :            :                     // Wir muessen zuerst einfuegen, da in SetAnchor()
    1255                 :            :                     // dem FlyFrm GetStart() uebermittelt wird.
    1256                 :            :                     //JP 11.05.98: falls das Anker-Attribut schon richtig
    1257                 :            :                     // gesetzt ist, dann korrigiere dieses nach dem Einfuegen
    1258                 :            :                     // des Zeichens. Sonst muesste das immer  ausserhalb
    1259                 :            :                     // erfolgen (Fehleranfaellig !)
    1260                 :        967 :                     const SwFmtAnchor* pAnchor = 0;
    1261                 :            :                     pFmt->GetItemState( RES_ANCHOR, sal_False,
    1262         [ +  - ]:        967 :                                             (const SfxPoolItem**)&pAnchor );
    1263                 :            : 
    1264         [ +  - ]:        967 :                     SwIndex aIdx( this, *pAttr->GetStart() );
    1265         [ +  - ]:        967 :                     const rtl::OUString c(GetCharOfTxtAttr(*pAttr));
    1266 [ +  - ][ +  - ]:        967 :                     InsertText( c, aIdx, nInsertFlags );
                 [ +  - ]
    1267                 :        967 :                     nInsMode |= nsSetAttrMode::SETATTR_NOTXTATRCHR;
    1268                 :            : 
    1269   [ +  -  +  - ]:       5802 :                     if (pAnchor &&
           [ +  -  +  -  
           +  - ][ +  - ]
    1270                 :        967 :                         (FLY_AS_CHAR == pAnchor->GetAnchorId()) &&
    1271         [ +  - ]:        967 :                         pAnchor->GetCntntAnchor() &&
    1272 [ +  - ][ +  - ]:       1934 :                         pAnchor->GetCntntAnchor()->nNode == *this &&
         [ +  - ][ +  - ]
                 [ #  # ]
    1273         [ +  - ]:        967 :                         pAnchor->GetCntntAnchor()->nContent == aIdx )
    1274                 :            :                     {
    1275                 :            :                         const_cast<SwIndex&>(
    1276 [ +  - ][ +  - ]:        967 :                             pAnchor->GetCntntAnchor()->nContent)--;
    1277         [ +  - ]:        967 :                     }
    1278                 :            :                 }
    1279                 :        970 :                 pFly->SetAnchor( this );
    1280                 :            : 
    1281                 :            :                 // Format-Pointer kann sich im SetAnchor geaendert haben!
    1282                 :            :                 // (Kopieren in andere Docs!)
    1283                 :        970 :                 pFmt = pAttr->GetFlyCnt().GetFrmFmt();
    1284                 :        970 :                 SwDoc *pDoc = pFmt->GetDoc();
    1285                 :            : 
    1286                 :            :                 // OD 26.06.2003 #108784# - allow drawing objects in header/footer.
    1287                 :            :                 // But don't allow control objects in header/footer
    1288         [ -  + ]:       1464 :                 if( RES_DRAWFRMFMT == pFmt->Which() &&
           [ +  +  -  + ]
    1289                 :        494 :                     pDoc->IsInHeaderFooter( pFmt->GetAnchor().GetCntntAnchor()->nNode ) )
    1290                 :            :                 {
    1291                 :            :                     SwDrawContact* pDrawContact =
    1292                 :          0 :                         static_cast<SwDrawContact*>(pFmt->FindContactObj());
    1293 [ #  # ][ #  #  :          0 :                     if ( pDrawContact &&
             #  #  #  # ]
    1294                 :          0 :                          pDrawContact->GetMaster() &&
    1295                 :          0 :                          ::CheckControlLayer( pDrawContact->GetMaster() ) )
    1296                 :            :                     {
    1297                 :            :                         // das soll nicht meoglich sein; hier verhindern
    1298                 :            :                         // Der Dtor des TxtHints loescht nicht das Zeichen.
    1299                 :            :                         // Wenn ein CH_TXTATR_.. vorliegt, dann muss man
    1300                 :            :                         // dieses explizit loeschen
    1301         [ #  # ]:          0 :                         if( nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode )
    1302                 :            :                         {
    1303                 :            :                             // loesche das Zeichen aus dem String !
    1304                 :            :                             OSL_ENSURE( ( CH_TXTATR_BREAKWORD ==
    1305                 :            :                                         m_Text.GetChar(*pAttr->GetStart() ) ||
    1306                 :            :                                       CH_TXTATR_INWORD ==
    1307                 :            :                                         m_Text.GetChar(*pAttr->GetStart())),
    1308                 :            :                                     "where is my attribute character?" );
    1309         [ #  # ]:          0 :                             m_Text.Erase( *pAttr->GetStart(), 1 );
    1310                 :            :                             // Indizies Updaten
    1311         [ #  # ]:          0 :                             SwIndex aTmpIdx( this, *pAttr->GetStart() );
    1312 [ #  # ][ #  # ]:          0 :                             Update( aTmpIdx, 1, sal_True );
    1313                 :            :                         }
    1314                 :            :                         // do not record deletion of Format!
    1315 [ #  # ][ #  # ]:          0 :                         ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
    1316         [ #  # ]:          0 :                         DestroyAttr( pAttr );
    1317         [ #  # ]:          0 :                         return false;
    1318                 :            :                     }
    1319                 :            :                 }
    1320                 :        970 :                 break;
    1321                 :            :             }
    1322                 :            : 
    1323                 :            :             case RES_TXTATR_FTN :
    1324                 :            :             {
    1325                 :            :                 // Fussnoten, man kommt an alles irgendwie heran.
    1326                 :            :                 // CntntNode erzeugen und in die Inserts-Section stellen
    1327                 :         72 :                 SwDoc *pDoc = GetDoc();
    1328         [ +  - ]:         72 :                 SwNodes &rNodes = pDoc->GetNodes();
    1329                 :            : 
    1330                 :            :                 // FussNote in nicht Content-/Redline-Bereich einfuegen ??
    1331         [ -  + ]:         72 :                 if( StartOfSectionIndex() < rNodes.GetEndOfAutotext().GetIndex() )
    1332                 :            :                 {
    1333                 :            :                     // das soll nicht meoglich sein; hier verhindern
    1334                 :            :                     // Der Dtor des TxtHints loescht nicht das Zeichen.
    1335                 :            :                     // Wenn ein CH_TXTATR_.. vorliegt, dann muss man
    1336                 :            :                     // dieses explizit loeschen
    1337         [ #  # ]:          0 :                     if( nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode )
    1338                 :            :                     {
    1339                 :            :                         // loesche das Zeichen aus dem String !
    1340                 :            :                         OSL_ENSURE( ( CH_TXTATR_BREAKWORD ==
    1341                 :            :                                       m_Text.GetChar(*pAttr->GetStart() ) ||
    1342                 :            :                                   CH_TXTATR_INWORD ==
    1343                 :            :                                       m_Text.GetChar(*pAttr->GetStart())),
    1344                 :            :                                 "where is my attribute character?" );
    1345         [ #  # ]:          0 :                         m_Text.Erase( *pAttr->GetStart(), 1 );
    1346                 :            :                         // Indizies Updaten
    1347         [ #  # ]:          0 :                         SwIndex aTmpIdx( this, *pAttr->GetStart() );
    1348 [ #  # ][ #  # ]:          0 :                         Update( aTmpIdx, 1, sal_True );
    1349                 :            :                     }
    1350         [ #  # ]:          0 :                     DestroyAttr( pAttr );
    1351                 :          0 :                     return false;
    1352                 :            :                 }
    1353                 :            : 
    1354                 :            :                 // wird eine neue Fussnote eingefuegt ??
    1355                 :         72 :                 sal_Bool bNewFtn = 0 == ((SwTxtFtn*)pAttr)->GetStartNode();
    1356         [ +  - ]:         72 :                 if( bNewFtn )
    1357                 :            :                 {
    1358         [ +  - ]:         72 :                     ((SwTxtFtn*)pAttr)->MakeNewTextSection( GetNodes() );
    1359                 :         72 :                     SwRegHistory* pHist = GetpSwpHints()
    1360         [ +  + ]:         72 :                         ? GetpSwpHints()->GetHistory() : 0;
    1361         [ +  + ]:         72 :                     if( pHist )
    1362                 :         34 :                         pHist->ChangeNodeIndex( GetIndex() );
    1363                 :            :                 }
    1364 [ #  # ][ #  # ]:          0 :                 else if ( !GetpSwpHints() || !GetpSwpHints()->IsInSplitNode() )
                 [ #  # ]
    1365                 :            :                 {
    1366                 :            :                     // loesche alle Frames der Section, auf die der StartNode zeigt
    1367                 :            :                     sal_uLong nSttIdx =
    1368                 :          0 :                         ((SwTxtFtn*)pAttr)->GetStartNode()->GetIndex();
    1369         [ #  # ]:          0 :                     sal_uLong nEndIdx = rNodes[ nSttIdx++ ]->EndOfSectionIndex();
    1370                 :            :                     SwCntntNode* pCNd;
    1371         [ #  # ]:          0 :                     for( ; nSttIdx < nEndIdx; ++nSttIdx )
    1372 [ #  # ][ #  # ]:          0 :                         if( 0 != ( pCNd = rNodes[ nSttIdx ]->GetCntntNode() ))
    1373         [ #  # ]:          0 :                             pCNd->DelFrms();
    1374                 :            :                 }
    1375                 :            : 
    1376         [ +  - ]:         72 :                 if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
    1377                 :            :                 {
    1378                 :            :                     // Wir muessen zuerst einfuegen, da sonst gleiche Indizes
    1379                 :            :                     // entstehen koennen und das Attribut im _SortArr_ am
    1380                 :            :                     // Dokument nicht eingetrage wird.
    1381         [ +  - ]:         72 :                     SwIndex aNdIdx( this, *pAttr->GetStart() );
    1382         [ +  - ]:         72 :                     const rtl::OUString c(GetCharOfTxtAttr(*pAttr));
    1383 [ +  - ][ +  - ]:         72 :                     InsertText( c, aNdIdx, nInsertFlags );
                 [ +  - ]
    1384         [ +  - ]:         72 :                     nInsMode |= nsSetAttrMode::SETATTR_NOTXTATRCHR;
    1385                 :            :                 }
    1386                 :            : 
    1387                 :            :                 // Wir tragen uns am FtnIdx-Array des Docs ein ...
    1388                 :         72 :                 SwTxtFtn* pTxtFtn = 0;
    1389         [ -  + ]:         72 :                 if( !bNewFtn )
    1390                 :            :                 {
    1391                 :            :                     // eine alte Ftn wird umgehaengt (z.B. SplitNode)
    1392         [ #  # ]:          0 :                     for( sal_uInt16 n = 0; n < pDoc->GetFtnIdxs().size(); ++n )
    1393 [ #  # ][ #  # ]:          0 :                         if( pAttr == pDoc->GetFtnIdxs()[n] )
    1394                 :            :                         {
    1395                 :            :                             // neuen Index zuweisen, dafuer aus dem SortArray
    1396                 :            :                             // loeschen und neu eintragen
    1397         [ #  # ]:          0 :                             pTxtFtn = pDoc->GetFtnIdxs()[n];
    1398 [ #  # ][ #  # ]:          0 :                             pDoc->GetFtnIdxs().erase( pDoc->GetFtnIdxs().begin() + n );
    1399                 :          0 :                             break;
    1400                 :            :                         }
    1401                 :            :                     // wenn ueber Undo der StartNode gesetzt wurde, kann
    1402                 :            :                     // der Index noch gar nicht in der Verwaltung stehen !!
    1403                 :            :                 }
    1404         [ +  - ]:         72 :                 if( !pTxtFtn )
    1405                 :         72 :                     pTxtFtn = (SwTxtFtn*)pAttr;
    1406                 :            : 
    1407                 :            :                 // fuers Update der Nummern und zum Sortieren
    1408                 :            :                 // muss der Node gesetzt sein.
    1409                 :         72 :                 ((SwTxtFtn*)pAttr)->ChgTxtNode( this );
    1410                 :            : 
    1411                 :            :                 // FussNote im Redline-Bereich NICHT ins FtnArray einfuegen!
    1412         [ +  - ]:         72 :                 if( StartOfSectionIndex() > rNodes.GetEndOfRedlines().GetIndex() )
    1413                 :            :                 {
    1414         [ +  - ]:         72 :                     const bool bSuccess = pDoc->GetFtnIdxs().insert(pTxtFtn).second;
    1415                 :            :                     OSL_ENSURE( bSuccess, "FtnIdx not inserted." );
    1416                 :            :                     (void) bSuccess; // unused in non-debug
    1417                 :            :                 }
    1418         [ +  - ]:         72 :                 SwNodeIndex aTmpIndex( *this );
    1419         [ +  - ]:         72 :                 pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex);
    1420 [ +  - ][ +  - ]:         72 :                 ((SwTxtFtn*)pAttr)->SetSeqRefNo();
    1421                 :            :             }
    1422                 :         72 :             break;
    1423                 :            : 
    1424                 :            :             case RES_TXTATR_FIELD:
    1425                 :            :                 {
    1426                 :            :                     // fuer HiddenParaFields Benachrichtigungsmechanismus
    1427                 :            :                     // anwerfen
    1428         [ -  + ]:       1549 :                     if( RES_HIDDENPARAFLD ==
    1429                 :       1549 :                         pAttr->GetFld().GetFld()->GetTyp()->Which() )
    1430                 :          0 :                     bHiddenPara = sal_True;
    1431                 :            :                 }
    1432                 :       1549 :                 break;
    1433                 :            : 
    1434                 :            :         }
    1435                 :            :         // Fuer SwTxtHints ohne Endindex werden CH_TXTATR_..
    1436                 :            :         // eingefuegt, aStart muss danach um einen zurueckgesetzt werden.
    1437                 :            :         // Wenn wir im SwTxtNode::Copy stehen, so wurde das Zeichen bereits
    1438                 :            :         // mitkopiert. In solchem Fall ist SETATTR_NOTXTATRCHR angegeben worden.
    1439         [ +  + ]:       2890 :         if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
    1440                 :            :         {
    1441         [ +  - ]:       1848 :             SwIndex aIdx( this, *pAttr->GetStart() );
    1442 [ +  - ][ +  - ]:       1848 :             InsertText( rtl::OUString(GetCharOfTxtAttr(*pAttr)), aIdx, nInsertFlags );
         [ +  - ][ +  - ]
    1443                 :            : 
    1444                 :            :             // adjust end of hint to account for inserted CH_TXTATR
    1445         [ +  - ]:       1848 :             xub_StrLen * const pEnd(pAttr->GetEnd());
    1446         [ +  + ]:       1848 :             if (pEnd)
    1447                 :            :             {
    1448                 :        194 :                 *pEnd = *pEnd + 1;
    1449         [ +  - ]:       1848 :             }
    1450                 :            :         }
    1451                 :            :     }
    1452                 :            : 
    1453                 :      19573 :     GetOrCreateSwpHints();
    1454                 :            : 
    1455                 :            :     // 4263: AttrInsert durch TextInsert => kein Adjust
    1456                 :      19573 :     const bool bRet = m_pSwpHints->TryInsertHint( pAttr, *this, nMode );
    1457                 :            : 
    1458 [ +  - ][ +  + ]:      19573 :     if (!bRet && bDummyChar)
    1459                 :            :     {
    1460                 :            :         // undo insertion of dummy character
    1461                 :            :         // N.B. cannot insert the dummy character after inserting the hint,
    1462                 :            :         // because if the hint has no extent it will be moved in InsertText,
    1463                 :            :         // resulting in infinite recursion
    1464         [ +  - ]:          4 :         if ( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nMode) )
    1465                 :            :         {
    1466                 :            :             OSL_ENSURE( ( CH_TXTATR_BREAKWORD == m_Text.GetChar(nStart) ||
    1467                 :            :                       CH_TXTATR_INWORD    == m_Text.GetChar(nStart) ),
    1468                 :            :                     "where is my attribute character?" );
    1469         [ +  - ]:          4 :             SwIndex aIdx( this, nStart );
    1470 [ +  - ][ +  - ]:          4 :             EraseText( aIdx, 1 );
    1471                 :            :         }
    1472                 :            :     }
    1473                 :            : 
    1474         [ -  + ]:      19573 :     if ( bHiddenPara )
    1475                 :            :     {
    1476                 :          0 :         SetCalcHiddenParaField();
    1477                 :            :     }
    1478                 :            : 
    1479                 :      19573 :     return bRet;
    1480                 :            : }
    1481                 :            : 
    1482                 :            : 
    1483                 :            : /*************************************************************************
    1484                 :            :  *                        SwTxtNode::DeleteAttribute()
    1485                 :            :  *************************************************************************/
    1486                 :            : 
    1487                 :         10 : void SwTxtNode::DeleteAttribute( SwTxtAttr * const pAttr )
    1488                 :            : {
    1489         [ -  + ]:         10 :     if ( !HasHints() )
    1490                 :            :     {
    1491                 :            :         OSL_FAIL("DeleteAttribute called, but text node without hints?");
    1492                 :         10 :         return;
    1493                 :            :     }
    1494                 :            : 
    1495         [ +  - ]:         10 :     if ( pAttr->HasDummyChar() )
    1496                 :            :     {
    1497                 :            :         // Unbedingt Copy-konstruieren!
    1498         [ +  - ]:         10 :         const SwIndex aIdx( this, *pAttr->GetStart() );
    1499                 :            :         // erase the CH_TXTATR, which will also delete pAttr
    1500 [ +  - ][ +  - ]:         10 :         EraseText( aIdx, 1 );
    1501                 :            :     }
    1502                 :            :     else
    1503                 :            :     {
    1504                 :            :         // create MsgHint before start/end become invalid
    1505                 :            :         SwUpdateAttr aHint(
    1506 [ #  # ][ #  # ]:          0 :                 *pAttr->GetStart(), *pAttr->GetEnd(), pAttr->Which() );
                 [ #  # ]
    1507         [ #  # ]:          0 :         m_pSwpHints->Delete( pAttr );
    1508         [ #  # ]:          0 :         SwTxtAttr::Destroy( pAttr, GetDoc()->GetAttrPool() );
    1509         [ #  # ]:          0 :         NotifyClients( 0, &aHint );
    1510                 :            : 
    1511 [ #  # ][ #  # ]:          0 :         TryDeleteSwpHints();
    1512                 :            :     }
    1513                 :            : }
    1514                 :            : 
    1515                 :            : /*************************************************************************
    1516                 :            :  *                        SwTxtNode::DeleteAttributes()
    1517                 :            :  *************************************************************************/
    1518                 :            : 
    1519                 :            : //FIXME: this does NOT respect SORT NUMBER (for CHARFMT)!
    1520                 :         20 : void SwTxtNode::DeleteAttributes( const sal_uInt16 nWhich,
    1521                 :            :     const xub_StrLen nStart, const xub_StrLen nEnd )
    1522                 :            : {
    1523         [ -  + ]:         20 :     if ( !HasHints() )
    1524                 :         20 :         return;
    1525                 :            : 
    1526 [ +  + ][ +  - ]:         42 :     for ( sal_uInt16 nPos = 0; m_pSwpHints && nPos < m_pSwpHints->Count(); nPos++ )
                 [ +  + ]
    1527                 :            :     {
    1528                 :         24 :         SwTxtAttr * const pTxtHt = m_pSwpHints->GetTextHint( nPos );
    1529                 :         24 :         const xub_StrLen nHintStart = *(pTxtHt->GetStart());
    1530         [ +  + ]:         24 :         if (nStart < nHintStart)
    1531                 :            :         {
    1532                 :          2 :             break; // sorted by start
    1533                 :            :         }
    1534 [ +  + ][ +  - ]:         22 :         else if ( (nStart == nHintStart) && (nWhich == pTxtHt->Which()) )
                 [ +  + ]
    1535                 :            :         {
    1536         [ -  + ]:         20 :             if ( nWhich == RES_CHRATR_HIDDEN  )
    1537                 :            :             {
    1538                 :            :                 OSL_FAIL("hey, that's a CHRATR! how did that get in?");
    1539                 :          0 :                 SetCalcHiddenCharFlags();
    1540                 :            :             }
    1541         [ -  + ]:         20 :             else if ( nWhich == RES_TXTATR_CHARFMT )
    1542                 :            :             {
    1543                 :            :                 // Check if character format contains hidden attribute:
    1544                 :          0 :                 const SwCharFmt* pFmt = pTxtHt->GetCharFmt().GetCharFmt();
    1545                 :            :                 const SfxPoolItem* pItem;
    1546 [ #  # ][ #  # ]:          0 :                 if ( SFX_ITEM_SET == pFmt->GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
    1547                 :          0 :                     SetCalcHiddenCharFlags();
    1548                 :            :             }
    1549                 :            :             // #i75430# Recalc hidden flags if necessary
    1550         [ -  + ]:         20 :             else if ( nWhich == RES_TXTATR_AUTOFMT )
    1551                 :            :             {
    1552                 :            :                 // Check if auto style contains hidden attribute:
    1553                 :          0 :                 const SfxPoolItem* pHiddenItem = CharFmt::GetItem( *pTxtHt, RES_CHRATR_HIDDEN );
    1554         [ #  # ]:          0 :                 if ( pHiddenItem )
    1555                 :          0 :                     SetCalcHiddenCharFlags();
    1556                 :            :             }
    1557                 :            : 
    1558                 :         20 :             xub_StrLen const * const pEndIdx = pTxtHt->GetEnd();
    1559                 :            : 
    1560         [ +  - ]:         20 :             if ( pTxtHt->HasDummyChar() )
    1561                 :            :             {
    1562                 :            :                 // Unbedingt Copy-konstruieren!
    1563         [ +  - ]:         20 :                 const SwIndex aIdx( this, nStart );
    1564                 :            :                 // erase the CH_TXTATR, which will also delete pTxtHt
    1565 [ +  - ][ +  - ]:         20 :                 EraseText( aIdx, 1 );
    1566                 :            :             }
    1567         [ #  # ]:          0 :             else if( *pEndIdx == nEnd )
    1568                 :            :             {
    1569                 :            :                 // den MsgHint jetzt fuettern, weil gleich sind
    1570                 :            :                 // Start und End weg.
    1571                 :            :                 // Das CalcVisibleFlag bei HiddenParaFields entfaellt,
    1572                 :            :                 // da dies das Feld im Dtor selbst erledigt.
    1573         [ #  # ]:          0 :                 SwUpdateAttr aHint( nStart, *pEndIdx, nWhich );
    1574         [ #  # ]:          0 :                 m_pSwpHints->DeleteAtPos( nPos );    // gefunden, loeschen,
    1575         [ #  # ]:          0 :                 SwTxtAttr::Destroy( pTxtHt, GetDoc()->GetAttrPool() );
    1576 [ #  # ][ #  # ]:          0 :                 NotifyClients( 0, &aHint );
    1577                 :            :             }
    1578                 :            :         }
    1579                 :            :     }
    1580                 :         20 :     TryDeleteSwpHints();
    1581                 :            : }
    1582                 :            : 
    1583                 :            : /*************************************************************************
    1584                 :            :  *                      SwTxtNode::DelSoftHyph()
    1585                 :            :  *************************************************************************/
    1586                 :            : 
    1587                 :          0 : void SwTxtNode::DelSoftHyph( const xub_StrLen nStt, const xub_StrLen nEnd )
    1588                 :            : {
    1589                 :          0 :     xub_StrLen nFndPos = nStt, nEndPos = nEnd;
    1590 [ #  # ][ #  # ]:          0 :     while( STRING_NOTFOUND !=
                 [ #  # ]
    1591                 :          0 :             ( nFndPos = m_Text.Search( CHAR_SOFTHYPHEN, nFndPos )) &&
    1592                 :            :             nFndPos < nEndPos )
    1593                 :            :     {
    1594         [ #  # ]:          0 :         const SwIndex aIdx( this, nFndPos );
    1595         [ #  # ]:          0 :         EraseText( aIdx, 1 );
    1596                 :          0 :         --nEndPos;
    1597         [ #  # ]:          0 :     }
    1598                 :          0 : }
    1599                 :            : 
    1600                 :            : // setze diese Attribute am TextNode. Wird der gesamte Bereich umspannt,
    1601                 :            : // dann setze sie nur im AutoAttrSet (SwCntntNode:: SetAttr)
    1602                 :      24508 : sal_Bool SwTxtNode::SetAttr( const SfxItemSet& rSet, xub_StrLen nStt,
    1603                 :            :                          xub_StrLen nEnd, const SetAttrMode nMode )
    1604                 :            : {
    1605         [ -  + ]:      24508 :     if( !rSet.Count() )
    1606                 :          0 :         return sal_False;
    1607                 :            : 
    1608                 :            :     // teil die Sets auf (fuer Selektion in Nodes)
    1609                 :      24508 :     const SfxItemSet* pSet = &rSet;
    1610         [ +  - ]:      24508 :     SfxItemSet aTxtSet( *rSet.GetPool(), RES_TXTATR_BEGIN, RES_TXTATR_END-1 );
    1611                 :            : 
    1612                 :            :     // gesamter Bereich
    1613 [ +  + ][ +  + ]:      24508 :     if ( !nStt && (nEnd == m_Text.Len()) &&
         [ +  + ][ +  + ]
    1614                 :      14488 :          !(nMode & nsSetAttrMode::SETATTR_NOFORMATATTR ) )
    1615                 :            :     {
    1616                 :            :         // sind am Node schon Zeichenvorlagen gesetzt, muss man diese Attribute
    1617                 :            :         // (rSet) immer als TextAttribute setzen, damit sie angezeigt werden.
    1618                 :      10264 :         int bHasCharFmts = sal_False;
    1619         [ +  + ]:      10264 :         if ( HasHints() )
    1620                 :            :         {
    1621         [ +  + ]:       6734 :             for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n )
    1622                 :            :             {
    1623 [ +  - ][ +  + ]:       5672 :                 if ( (*m_pSwpHints)[ n ]->IsCharFmtAttr() )
    1624                 :            :                 {
    1625                 :        108 :                     bHasCharFmts = sal_True;
    1626                 :        108 :                     break;
    1627                 :            :                 }
    1628                 :            :             }
    1629                 :            :         }
    1630                 :            : 
    1631         [ +  + ]:      10264 :         if( !bHasCharFmts )
    1632                 :            :         {
    1633         [ +  - ]:      10156 :             aTxtSet.Put( rSet );
    1634                 :            :             // If there are any character attributes in rSet,
    1635                 :            :             // we want to set them at the paragraph:
    1636         [ +  + ]:      10156 :             if( aTxtSet.Count() != rSet.Count() )
    1637                 :            :             {
    1638         [ +  - ]:       9738 :                 sal_Bool bRet = SetAttr( rSet );
    1639         [ +  - ]:       9738 :                   if( !aTxtSet.Count() )
    1640                 :       9738 :                     return bRet;
    1641                 :            :             }
    1642                 :            : 
    1643                 :            :             // check for auto style:
    1644                 :            :             const SfxPoolItem* pItem;
    1645         [ +  - ]:        418 :             const bool bAutoStyle = SFX_ITEM_SET == aTxtSet.GetItemState( RES_TXTATR_AUTOFMT, sal_False, &pItem );
    1646         [ +  + ]:        418 :             if ( bAutoStyle )
    1647                 :            :             {
    1648         [ +  - ]:          6 :                 boost::shared_ptr<SfxItemSet> pAutoStyleSet = static_cast<const SwFmtAutoFmt*>(pItem)->GetStyleHandle();
    1649         [ +  - ]:          6 :                 sal_Bool bRet = SetAttr( *pAutoStyleSet );
    1650         [ +  - ]:          6 :                   if( 1 == aTxtSet.Count() )
    1651 [ +  - ][ -  + ]:          6 :                     return bRet;
    1652                 :            :             }
    1653                 :            : 
    1654                 :            :             // Continue with the text attributes:
    1655                 :      10156 :             pSet = &aTxtSet;
    1656                 :            :         }
    1657                 :            :     }
    1658                 :            : 
    1659         [ +  - ]:      14764 :     GetOrCreateSwpHints();
    1660                 :            : 
    1661         [ +  - ]:      14764 :     SfxItemSet aCharSet( *rSet.GetPool(), aCharAutoFmtSetRange );
    1662                 :            : 
    1663                 :      14764 :     sal_uInt16 nCount = 0;
    1664         [ +  - ]:      14764 :     SfxItemIter aIter( *pSet );
    1665                 :      14764 :     const SfxPoolItem* pItem = aIter.GetCurItem();
    1666                 :            : 
    1667                 :          0 :     do
    1668                 :            :     {
    1669 [ +  - ][ +  - ]:      14764 :         if ( pItem && (reinterpret_cast<SfxPoolItem*>(-1) != pItem))
    1670                 :            :         {
    1671                 :      14764 :             const sal_uInt16 nWhich = pItem->Which();
    1672                 :            :             OSL_ENSURE( isCHRATR(nWhich) || isTXTATR(nWhich),
    1673                 :            :                     "SwTxtNode::SetAttr(): unknown attribute" );
    1674 [ +  - ][ +  - ]:      14764 :             if ( isCHRATR(nWhich) || isTXTATR(nWhich) )
                 [ +  + ]
    1675                 :            :             {
    1676   [ +  +  -  + ]:      14807 :                 if ((RES_TXTATR_CHARFMT == nWhich) &&
                 [ -  + ]
    1677                 :         43 :                     (GetDoc()->GetDfltCharFmt() ==
    1678                 :         43 :                      static_cast<const SwFmtCharFmt*>(pItem)->GetCharFmt()))
    1679                 :            :                 {
    1680         [ #  # ]:          0 :                     SwIndex aIndex( this, nStt );
    1681         [ #  # ]:          0 :                     RstAttr( aIndex, nEnd - nStt, RES_TXTATR_CHARFMT, 0 );
    1682 [ #  # ][ #  # ]:          0 :                     DontExpandFmt( aIndex );
    1683                 :            :                 }
    1684                 :            :                 else
    1685                 :            :                 {
    1686 [ +  + ][ +  + ]:      14764 :                     if (isCHRATR(nWhich) ||
                 [ +  + ]
    1687                 :            :                         (RES_TXTATR_UNKNOWN_CONTAINER == nWhich))
    1688                 :            :                     {
    1689         [ +  - ]:      12330 :                         aCharSet.Put( *pItem );
    1690                 :            :                     }
    1691                 :            :                     else
    1692                 :            :                     {
    1693                 :            : 
    1694                 :       2434 :                         SwTxtAttr *const pNew = MakeTxtAttr( *GetDoc(),
    1695         [ +  - ]:       2434 :                                 const_cast<SfxPoolItem&>(*pItem), nStt, nEnd );
    1696         [ +  - ]:       2434 :                         if ( pNew )
    1697                 :            :                         {
    1698 [ +  + ][ +  - ]:       2434 :                             if ( nEnd != nStt && !pNew->GetEnd() )
         [ -  + ][ -  + ]
    1699                 :            :                             {
    1700                 :            :                                 OSL_FAIL("Attribut without end, but area marked");
    1701         [ #  # ]:          0 :                                 DestroyAttr( pNew ); // do not insert
    1702                 :            :                             }
    1703 [ +  - ][ +  + ]:       2434 :                             else if ( InsertHint( pNew, nMode ) )
    1704                 :            :                             {
    1705                 :       2430 :                                 ++nCount;
    1706                 :            :                             }
    1707                 :            :                         }
    1708                 :            :                     }
    1709                 :            :                 }
    1710                 :            :             }
    1711                 :            :         }
    1712         [ +  - ]:      14764 :         if ( aIter.IsAtEnd() )
    1713                 :      14764 :             break;
    1714         [ #  # ]:          0 :         pItem = aIter.NextItem();
    1715                 :            :     } while( true );
    1716                 :            : 
    1717         [ +  + ]:      14764 :     if ( aCharSet.Count() )
    1718                 :            :     {
    1719         [ +  - ]:      12330 :         SwTxtAttr* pTmpNew = MakeTxtAttr( *GetDoc(), aCharSet, nStt, nEnd );
    1720 [ +  - ][ +  - ]:      12330 :         if ( InsertHint( pTmpNew, nMode ) )
    1721                 :            :         {
    1722                 :      12330 :             ++nCount;
    1723                 :            :         }
    1724                 :            :     }
    1725                 :            : 
    1726         [ +  - ]:      14764 :     TryDeleteSwpHints();
    1727                 :            : 
    1728 [ +  + ][ +  - ]:      24508 :     return nCount ? sal_True : sal_False;
         [ +  - ][ +  - ]
    1729                 :            : }
    1730                 :            : 
    1731                 :         34 : void lcl_MergeAttr( SfxItemSet& rSet, const SfxPoolItem& rAttr )
    1732                 :            : {
    1733         [ +  + ]:         34 :     if ( RES_TXTATR_AUTOFMT == rAttr.Which() )
    1734                 :            :     {
    1735         [ +  - ]:          8 :         const SfxItemSet* pCFSet = CharFmt::GetItemSet( rAttr );
    1736         [ +  - ]:          8 :         if ( !pCFSet )
    1737                 :         34 :             return;
    1738         [ +  - ]:          8 :         SfxWhichIter aIter( *pCFSet );
    1739         [ +  - ]:          8 :         sal_uInt16 nWhich = aIter.FirstWhich();
    1740         [ +  + ]:        344 :         while( nWhich )
    1741                 :            :         {
    1742 [ +  + ][ +  + ]:        664 :             if( ( nWhich < RES_CHRATR_END ||
         [ +  + ][ +  + ]
    1743                 :            :                   RES_TXTATR_UNKNOWN_CONTAINER == nWhich ) &&
    1744         [ +  - ]:        328 :                 ( SFX_ITEM_SET == pCFSet->GetItemState( nWhich, sal_True ) ) )
    1745 [ +  - ][ +  - ]:         88 :                 rSet.Put( pCFSet->Get( nWhich ) );
    1746         [ +  - ]:        336 :             nWhich = aIter.NextWhich();
    1747         [ +  - ]:          8 :         }
    1748                 :            :     }
    1749                 :            :     else
    1750                 :         26 :         rSet.Put( rAttr );
    1751                 :            : }
    1752                 :            : 
    1753                 :      17859 : void lcl_MergeAttr_ExpandChrFmt( SfxItemSet& rSet, const SfxPoolItem& rAttr )
    1754                 :            : {
    1755   [ +  +  +  +  :      52360 :     if( RES_TXTATR_CHARFMT == rAttr.Which() ||
           +  + ][ +  + ]
    1756                 :      17426 :         RES_TXTATR_INETFMT == rAttr.Which() ||
    1757                 :      17075 :         RES_TXTATR_AUTOFMT == rAttr.Which() )
    1758                 :            :     {
    1759                 :      14917 :         const SfxItemSet* pCFSet = CharFmt::GetItemSet( rAttr );
    1760                 :            : 
    1761         [ +  + ]:      14917 :         if ( pCFSet )
    1762                 :            :         {
    1763         [ +  - ]:      14810 :             SfxWhichIter aIter( *pCFSet );
    1764         [ +  - ]:      14810 :             sal_uInt16 nWhich = aIter.FirstWhich();
    1765         [ +  + ]:     636153 :             while( nWhich )
    1766                 :            :             {
    1767   [ +  +  +  + ]:    1256819 :                 if( ( nWhich < RES_CHRATR_END ||
         [ +  + ][ +  + ]
                 [ +  + ]
    1768                 :      28943 :                       ( RES_TXTATR_AUTOFMT == rAttr.Which() && RES_TXTATR_UNKNOWN_CONTAINER == nWhich ) ) &&
    1769         [ +  - ]:     606533 :                     ( SFX_ITEM_SET == pCFSet->GetItemState( nWhich, sal_True ) ) )
    1770 [ +  - ][ +  - ]:      67541 :                     rSet.Put( pCFSet->Get( nWhich ) );
    1771         [ +  - ]:     621343 :                 nWhich = aIter.NextWhich();
    1772         [ +  - ]:      14810 :             }
    1773                 :            :         }
    1774                 :            :     }
    1775                 :            : 
    1776                 :            :     // aufnehmen als MergeWert (falls noch nicht gesetzt neu setzen!)
    1777                 :            : 
    1778                 :            : /* wenn mehrere Attribute ueberlappen gewinnt der letze !!
    1779                 :            :  z.B
    1780                 :            :             1234567890123456789
    1781                 :            :               |------------|        Font1
    1782                 :            :                  |------|           Font2
    1783                 :            :                     ^  ^
    1784                 :            :                     |--|        Abfragebereich: -> Gueltig ist Font2
    1785                 :            : */
    1786                 :      17859 :     rSet.Put( rAttr );
    1787                 :      17859 : }
    1788                 :            : 
    1789                 :            : struct SwPoolItemEndPair
    1790                 :            : {
    1791                 :            : public:
    1792                 :            :     const SfxPoolItem* mpItem;
    1793                 :            :     xub_StrLen mnEndPos;
    1794                 :            : 
    1795                 :       3500 :     SwPoolItemEndPair() : mpItem( 0 ), mnEndPos( 0 ) {};
    1796                 :            : };
    1797                 :            : 
    1798                 :        704 : void lcl_MergeListLevelIndentAsLRSpaceItem( const SwTxtNode& rTxtNode,
    1799                 :            :                                             SfxItemSet& rSet )
    1800                 :            : {
    1801         [ -  + ]:        704 :     if ( rTxtNode.AreListLevelIndentsApplicable() )
    1802                 :            :     {
    1803                 :          0 :         const SwNumRule* pRule = rTxtNode.GetNumRule();
    1804 [ #  # ][ #  # ]:          0 :         if ( pRule && rTxtNode.GetActualListLevel() >= 0 )
                 [ #  # ]
    1805                 :            :         {
    1806                 :          0 :             const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(rTxtNode.GetActualListLevel()));
    1807         [ #  # ]:          0 :             if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
    1808                 :            :             {
    1809         [ #  # ]:          0 :                 SvxLRSpaceItem aLR( RES_LR_SPACE );
    1810 [ #  # ][ #  # ]:          0 :                 aLR.SetTxtLeft( rFmt.GetIndentAt() );
    1811 [ #  # ][ #  # ]:          0 :                 aLR.SetTxtFirstLineOfst( static_cast<short>(rFmt.GetFirstLineIndent()) );
    1812 [ #  # ][ #  # ]:          0 :                 rSet.Put( aLR );
    1813                 :            :             }
    1814                 :            :         }
    1815                 :            :     }
    1816                 :        704 : }
    1817                 :            : 
    1818                 :            : // erfrage die Attribute vom TextNode ueber den Bereich
    1819                 :      74450 : sal_Bool SwTxtNode::GetAttr( SfxItemSet& rSet, xub_StrLen nStt, xub_StrLen nEnd,
    1820                 :            :                          sal_Bool bOnlyTxtAttr, sal_Bool bGetFromChrFmt,
    1821                 :            :                          const bool bMergeIndentValuesOfNumRule ) const
    1822                 :            : {
    1823         [ +  + ]:      74450 :     if( HasHints() )
    1824                 :            :     {
    1825                 :            :         /* stelle erstmal fest, welche Text-Attribut in dem Bereich gueltig
    1826                 :            :          * sind. Dabei gibt es folgende Faelle:
    1827                 :            :          *  UnEindeutig wenn: (wenn != Format-Attribut)
    1828                 :            :          *      - das Attribut liegt vollstaendig im Bereich
    1829                 :            :          *      - das Attributende liegt im Bereich
    1830                 :            :          *      - der Attributanfang liegt im Bereich:
    1831                 :            :          * Eindeutig (im Set mergen):
    1832                 :            :          *      - das Attrib umfasst den Bereich
    1833                 :            :          * nichts tun:
    1834                 :            :          *      das Attribut liegt ausserhalb des Bereiches
    1835                 :            :          */
    1836                 :            : 
    1837                 :            :         void (*fnMergeAttr)( SfxItemSet&, const SfxPoolItem& )
    1838                 :            :             = bGetFromChrFmt ? &lcl_MergeAttr_ExpandChrFmt
    1839         [ +  + ]:      22731 :                              : &lcl_MergeAttr;
    1840                 :            : 
    1841                 :            :         // dann besorge mal die Auto-(Fmt)Attribute
    1842         [ +  - ]:      22731 :         SfxItemSet aFmtSet( *rSet.GetPool(), rSet.GetRanges() );
    1843         [ +  + ]:      22731 :         if( !bOnlyTxtAttr )
    1844                 :            :         {
    1845         [ +  - ]:      22706 :             SwCntntNode::GetAttr( aFmtSet );
    1846         [ +  + ]:      22706 :             if ( bMergeIndentValuesOfNumRule )
    1847                 :            :             {
    1848         [ +  - ]:        388 :                 lcl_MergeListLevelIndentAsLRSpaceItem( *this, aFmtSet );
    1849                 :            :             }
    1850                 :            :         }
    1851                 :            : 
    1852                 :      22731 :         const sal_uInt16 nSize = m_pSwpHints->Count();
    1853                 :            : 
    1854         [ +  + ]:      22731 :         if( nStt == nEnd )             // kein Bereich:
    1855                 :            :         {
    1856         [ +  + ]:     374037 :             for (sal_uInt16 n = 0; n < nSize; ++n)
    1857                 :            :             {
    1858         [ +  - ]:     360867 :                 const SwTxtAttr* pHt = (*m_pSwpHints)[n];
    1859                 :     360867 :                 const xub_StrLen nAttrStart = *pHt->GetStart();
    1860         [ +  + ]:     360867 :                 if( nAttrStart > nEnd )         // ueber den Bereich hinaus
    1861                 :        188 :                     break;
    1862                 :            : 
    1863         [ +  - ]:     360679 :                 const xub_StrLen* pAttrEnd = pHt->GetEnd();
    1864         [ +  + ]:     360679 :                 if ( ! pAttrEnd ) // no attributes without end
    1865                 :     350359 :                     continue;
    1866                 :            : 
    1867   [ +  +  +  + ]:      15294 :                 if( ( nAttrStart < nStt &&
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
    1868                 :       4974 :                         ( pHt->DontExpand() ? nStt < *pAttrEnd
    1869                 :            :                                             : nStt <= *pAttrEnd )) ||
    1870                 :            :                     ( nStt == nAttrStart &&
    1871                 :            :                         ( nAttrStart == *pAttrEnd || !nStt )))
    1872         [ +  - ]:       8246 :                     (*fnMergeAttr)( rSet, pHt->GetAttr() );
    1873                 :            :             }
    1874                 :            :         }
    1875                 :            :         else                            // es ist ein Bereich definiert
    1876                 :            :         {
    1877                 :            :             // #i75299#
    1878                 :       9561 :             ::std::auto_ptr< std::vector< SwPoolItemEndPair > > pAttrArr;
    1879                 :            : 
    1880                 :            :             const sal_uInt16 coArrSz = static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) -
    1881                 :       9561 :                                    static_cast<sal_uInt16>(RES_CHRATR_BEGIN);
    1882                 :            : 
    1883         [ +  + ]:      27934 :             for (sal_uInt16 n = 0; n < nSize; ++n)
    1884                 :            :             {
    1885         [ +  - ]:      18821 :                 const SwTxtAttr* pHt = (*m_pSwpHints)[n];
    1886                 :      18821 :                 const xub_StrLen nAttrStart = *pHt->GetStart();
    1887         [ +  + ]:      18821 :                 if( nAttrStart > nEnd )         // ueber den Bereich hinaus
    1888                 :        448 :                     break;
    1889                 :            : 
    1890         [ +  - ]:      18373 :                 const xub_StrLen* pAttrEnd = pHt->GetEnd();
    1891         [ +  + ]:      18373 :                 if ( ! pAttrEnd ) // no attributes without end
    1892                 :        794 :                     continue;
    1893                 :            : 
    1894                 :      17579 :                 sal_Bool bChkInvalid = sal_False;
    1895         [ +  + ]:      17579 :                 if( nAttrStart <= nStt )       // vor oder genau Start
    1896                 :            :                 {
    1897         [ +  + ]:      16668 :                     if( *pAttrEnd <= nStt )    // liegt davor
    1898                 :       6973 :                         continue;
    1899                 :            : 
    1900         [ +  + ]:       9695 :                     if( nEnd <= *pAttrEnd )     // hinter oder genau Ende
    1901         [ +  - ]:       9647 :                         (*fnMergeAttr)( aFmtSet, pHt->GetAttr() );
    1902                 :            :                     else
    1903                 :            : //                  else if( pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
    1904                 :            :                         // uneindeutig
    1905                 :         48 :                         bChkInvalid = sal_True;
    1906                 :            :                 }
    1907         [ +  + ]:        911 :                 else if( nAttrStart < nEnd      // reicht in den Bereich
    1908                 :            : )//                      && pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
    1909                 :        115 :                     bChkInvalid = sal_True;
    1910                 :            : 
    1911         [ +  + ]:      10606 :                 if( bChkInvalid )
    1912                 :            :                 {
    1913                 :            :                     // uneindeutig ?
    1914                 :        163 :                     ::std::auto_ptr< SfxItemIter > pItemIter;
    1915                 :        163 :                     const SfxPoolItem* pItem = 0;
    1916                 :            : 
    1917 [ +  + ][ +  - ]:        163 :                     if ( RES_TXTATR_AUTOFMT == pHt->Which() )
    1918                 :            :                     {
    1919         [ +  - ]:         21 :                         const SfxItemSet* pAutoSet = CharFmt::GetItemSet( pHt->GetAttr() );
    1920         [ +  - ]:         21 :                         if ( pAutoSet )
    1921                 :            :                         {
    1922 [ +  - ][ +  - ]:         21 :                             pItemIter.reset( new SfxItemIter( *pAutoSet ) );
    1923                 :         21 :                             pItem = pItemIter->GetCurItem();
    1924                 :            :                         }
    1925                 :            :                     }
    1926                 :            :                     else
    1927                 :        142 :                         pItem = &pHt->GetAttr();
    1928                 :            : 
    1929                 :        163 :                     const sal_uInt16 nHintEnd = *pAttrEnd;
    1930                 :            : 
    1931         [ +  + ]:        347 :                     while ( pItem )
    1932                 :            :                     {
    1933                 :        184 :                         const sal_uInt16 nHintWhich = pItem->Which();
    1934                 :            :                         OSL_ENSURE(!isUNKNOWNATR(nHintWhich),
    1935                 :            :                                 "SwTxtNode::GetAttr(): unknown attribute?");
    1936                 :            : 
    1937         [ +  + ]:        184 :                         if ( !pAttrArr.get() )
    1938                 :            :                         {
    1939                 :            :                             pAttrArr.reset(
    1940 [ +  - ][ +  - ]:         70 :                                 new std::vector< SwPoolItemEndPair >(coArrSz));
    1941                 :            :                         }
    1942                 :            : 
    1943                 :        184 :                         std::vector< SwPoolItemEndPair >::iterator pPrev = pAttrArr->begin();
    1944         [ +  - ]:        326 :                         if (isCHRATR(nHintWhich) ||
           [ +  +  +  - ]
    1945                 :        142 :                             isTXTATR_WITHEND(nHintWhich))
    1946                 :            :                         {
    1947                 :        184 :                             pPrev += nHintWhich - RES_CHRATR_BEGIN;
    1948                 :            :                         }
    1949                 :            :                         else
    1950                 :            :                         {
    1951                 :          0 :                             pPrev = pAttrArr->end();
    1952                 :            :                         }
    1953                 :            : 
    1954 [ +  - ][ +  - ]:        184 :                         if( pPrev != pAttrArr->end() )
    1955                 :            :                         {
    1956         [ +  + ]:        184 :                             if( !pPrev->mpItem )
    1957                 :            :                             {
    1958 [ +  - ][ +  - ]:         91 :                                 if ( bOnlyTxtAttr || *pItem != aFmtSet.Get( nHintWhich ) )
         [ +  - ][ +  - ]
                 [ +  - ]
    1959                 :            :                                 {
    1960         [ +  + ]:         91 :                                     if( nAttrStart > nStt )
    1961                 :            :                                     {
    1962         [ +  - ]:         45 :                                         rSet.InvalidateItem( nHintWhich );
    1963                 :         45 :                                         pPrev->mpItem = (SfxPoolItem*)-1;
    1964                 :            :                                     }
    1965                 :            :                                     else
    1966                 :            :                                     {
    1967                 :         46 :                                         pPrev->mpItem = pItem;
    1968                 :         46 :                                         pPrev->mnEndPos = nHintEnd;
    1969                 :            :                                     }
    1970                 :            :                                 }
    1971                 :            :                             }
    1972         [ +  + ]:         93 :                             else if( (SfxPoolItem*)-1 != pPrev->mpItem )
    1973                 :            :                             {
    1974 [ +  + ][ +  + ]:         42 :                                 if( pPrev->mnEndPos == nAttrStart &&
                 [ +  + ]
    1975         [ +  - ]:         12 :                                     *pPrev->mpItem == *pItem )
    1976                 :            :                                 {
    1977                 :          6 :                                     pPrev->mpItem = pItem;
    1978                 :          6 :                                     pPrev->mnEndPos = nHintEnd;
    1979                 :            :                                 }
    1980                 :            :                                 else
    1981                 :            :                                 {
    1982         [ +  - ]:         24 :                                     rSet.InvalidateItem( nHintWhich );
    1983                 :         24 :                                     pPrev->mpItem = (SfxPoolItem*)-1;
    1984                 :            :                                 }
    1985                 :            :                             }
    1986                 :            :                         }
    1987                 :            : 
    1988                 :        226 :                         pItem = ( pItemIter.get() && !pItemIter->IsAtEnd() )
    1989         [ +  - ]:        226 :                                     ? pItemIter->NextItem() : 0;
           [ +  +  +  + ]
    1990         [ +  - ]:        163 :                     } // end while
    1991                 :            :                 }
    1992                 :            :             }
    1993                 :            : 
    1994         [ +  + ]:       9561 :             if ( pAttrArr.get() )
    1995                 :            :             {
    1996         [ +  + ]:       3570 :                 for (sal_uInt16 n = 0; n < coArrSz; ++n)
    1997                 :            :                 {
    1998                 :       3500 :                     const SwPoolItemEndPair& rItemPair = (*pAttrArr)[ n ];
    1999 [ +  + ][ +  + ]:       3500 :                     if( (0 != rItemPair.mpItem) && ((SfxPoolItem*)-1 != rItemPair.mpItem) )
    2000                 :            :                     {
    2001                 :            :                         const sal_uInt16 nWh =
    2002                 :         22 :                             static_cast<sal_uInt16>(n + RES_CHRATR_BEGIN);
    2003                 :            : 
    2004         [ -  + ]:         22 :                         if( nEnd <= rItemPair.mnEndPos ) // hinter oder genau Ende
    2005                 :            :                         {
    2006 [ #  # ][ #  # ]:          0 :                             if( *rItemPair.mpItem != aFmtSet.Get( nWh ) )
                 [ #  # ]
    2007         [ #  # ]:          0 :                                 (*fnMergeAttr)( rSet, *rItemPair.mpItem );
    2008                 :            :                         }
    2009                 :            :                         else
    2010                 :            :                             // uneindeutig
    2011         [ +  - ]:         22 :                             rSet.InvalidateItem( nWh );
    2012                 :            :                     }
    2013                 :            :                 }
    2014                 :       9561 :             }
    2015                 :            :         }
    2016         [ +  + ]:      22731 :         if( aFmtSet.Count() )
    2017                 :            :         {
    2018                 :            :             // aus dem Format-Set alle entfernen, die im TextSet auch gesetzt sind
    2019         [ +  - ]:       9865 :             aFmtSet.Differentiate( rSet );
    2020                 :            :             // jetzt alle zusammen "mergen"
    2021         [ +  - ]:       9865 :             rSet.Put( aFmtSet );
    2022         [ +  - ]:      22731 :         }
    2023                 :            :     }
    2024         [ +  + ]:      51719 :     else if( !bOnlyTxtAttr )
    2025                 :            :     {
    2026                 :            :         // dann besorge mal die Auto-(Fmt)Attribute
    2027                 :      51699 :         SwCntntNode::GetAttr( rSet );
    2028         [ +  + ]:      51699 :         if ( bMergeIndentValuesOfNumRule )
    2029                 :            :         {
    2030                 :        316 :             lcl_MergeListLevelIndentAsLRSpaceItem( *this, rSet );
    2031                 :            :         }
    2032                 :            :     }
    2033                 :            : 
    2034         [ +  + ]:      74450 :     return rSet.Count() ? sal_True : sal_False;
    2035                 :            : }
    2036                 :            : 
    2037                 :            : 
    2038                 :            : namespace
    2039                 :            : {
    2040                 :            : 
    2041                 :            : typedef std::pair<sal_uInt16, sal_uInt16> AttrSpan_t;
    2042                 :            : typedef std::multimap<AttrSpan_t, const SwTxtAttr*> AttrSpanMap_t;
    2043                 :            : 
    2044                 :            : 
    2045                 :            : struct IsAutoStyle
    2046                 :            : {
    2047                 :            :     bool
    2048                 :          0 :     operator()(const AttrSpanMap_t::value_type& i_rAttrSpan)
    2049                 :            :     const
    2050                 :            :     {
    2051 [ #  # ][ #  # ]:          0 :         return i_rAttrSpan.second && i_rAttrSpan.second->Which() == RES_TXTATR_AUTOFMT;
    2052                 :            :     }
    2053                 :            : };
    2054                 :            : 
    2055                 :            : 
    2056                 :            : /** Removes from io_rAttrSet all items that are set by style on the
    2057                 :            :     given span.
    2058                 :            :   */
    2059                 :            : struct RemovePresentAttrs
    2060                 :            : {
    2061                 :          0 :     RemovePresentAttrs(SfxItemSet& io_rAttrSet)
    2062                 :          0 :         : m_rAttrSet(io_rAttrSet)
    2063                 :            :     {
    2064                 :          0 :     }
    2065                 :            : 
    2066                 :            :     void
    2067                 :          0 :     operator()(const AttrSpanMap_t::value_type& i_rAttrSpan)
    2068                 :            :     const
    2069                 :            :     {
    2070         [ #  # ]:          0 :         if (!i_rAttrSpan.second)
    2071                 :            :         {
    2072                 :          0 :             return;
    2073                 :            :         }
    2074                 :            : 
    2075                 :          0 :         const SwTxtAttr* const pAutoStyle(i_rAttrSpan.second);
    2076         [ #  # ]:          0 :         SfxItemIter aIter(m_rAttrSet);
    2077                 :          0 :         const SfxPoolItem* pItem(aIter.GetCurItem());
    2078         [ #  # ]:          0 :         while (pItem)
    2079                 :            :         {
    2080                 :          0 :             const sal_uInt16 nWhich(pItem->Which());
    2081 [ #  # ][ #  # ]:          0 :             if (CharFmt::IsItemIncluded(nWhich, pAutoStyle))
    2082                 :            :             {
    2083         [ #  # ]:          0 :                 m_rAttrSet.ClearItem(nWhich);
    2084                 :            :             }
    2085                 :            : 
    2086         [ #  # ]:          0 :             if (aIter.IsAtEnd())
    2087                 :            :             {
    2088                 :          0 :                 break;
    2089                 :            :             }
    2090         [ #  # ]:          0 :             pItem = aIter.NextItem();
    2091         [ #  # ]:          0 :         }
    2092                 :            :     }
    2093                 :            : 
    2094                 :            : private:
    2095                 :            :     SfxItemSet& m_rAttrSet;
    2096                 :            : };
    2097                 :            : 
    2098                 :            : 
    2099                 :            : /** Collects all style-covered spans from i_rHints to o_rSpanMap. In
    2100                 :            :     addition inserts dummy spans with pointer to format equal to 0 for
    2101                 :            :     all gaps (i.e. spans not covered by any style). This simplifies
    2102                 :            :     creation of autostyles for all needed spans, but it means all code
    2103                 :            :     that tries to access the pointer has to check if it's non-null!
    2104                 :            :  */
    2105                 :            : void
    2106                 :          0 : lcl_CollectHintSpans(const SwpHints& i_rHints, const sal_uInt16 nLength,
    2107                 :            :         AttrSpanMap_t& o_rSpanMap)
    2108                 :            : {
    2109                 :          0 :     sal_uInt16 nLastEnd(0);
    2110                 :            : 
    2111         [ #  # ]:          0 :     for (sal_uInt16 i(0); i != i_rHints.Count(); ++i)
    2112                 :            :     {
    2113         [ #  # ]:          0 :         const SwTxtAttr* const pHint(i_rHints[i]);
    2114         [ #  # ]:          0 :         const sal_uInt16 nWhich(pHint->Which());
    2115 [ #  # ][ #  # ]:          0 :         if (nWhich == RES_TXTATR_CHARFMT || nWhich == RES_TXTATR_AUTOFMT)
    2116                 :            :         {
    2117 [ #  # ][ #  # ]:          0 :             const AttrSpan_t aSpan(*pHint->GetStart(), *pHint->GetEnd());
    2118         [ #  # ]:          0 :             o_rSpanMap.insert(AttrSpanMap_t::value_type(aSpan, pHint));
    2119                 :            : 
    2120                 :            :             // < not != because there may be multiple CHARFMT at same range
    2121         [ #  # ]:          0 :             if (nLastEnd < aSpan.first)
    2122                 :            :             {
    2123                 :            :                 // insert dummy span covering the gap
    2124                 :            :                 o_rSpanMap.insert(AttrSpanMap_t::value_type(
    2125 [ #  # ][ #  # ]:          0 :                             AttrSpan_t(nLastEnd, aSpan.first), 0));
                 [ #  # ]
    2126                 :            :             }
    2127                 :            : 
    2128                 :          0 :             nLastEnd = aSpan.second;
    2129                 :            :         }
    2130                 :            :     }
    2131                 :            : 
    2132                 :            :     // no hints at the end (special case: no hints at all in i_rHints)
    2133 [ #  # ][ #  # ]:          0 :     if (nLastEnd != nLength && nLength != 0)
    2134                 :            :     {
    2135                 :            :         o_rSpanMap.insert(
    2136 [ #  # ][ #  # ]:          0 :             AttrSpanMap_t::value_type(AttrSpan_t(nLastEnd, nLength), 0));
                 [ #  # ]
    2137                 :            :     }
    2138                 :          0 : }
    2139                 :            : 
    2140                 :            : 
    2141                 :            : void
    2142                 :          0 : lcl_FillWhichIds(const SfxItemSet& i_rAttrSet, std::vector<sal_uInt16>& o_rClearIds)
    2143                 :            : {
    2144         [ #  # ]:          0 :     o_rClearIds.reserve(i_rAttrSet.Count());
    2145         [ #  # ]:          0 :     SfxItemIter aIter(i_rAttrSet);
    2146                 :          0 :     const SfxPoolItem* pItem(aIter.GetCurItem());
    2147         [ #  # ]:          0 :     while (pItem)
    2148                 :            :     {
    2149         [ #  # ]:          0 :         o_rClearIds.push_back(pItem->Which());
    2150                 :            : 
    2151         [ #  # ]:          0 :         if (aIter.IsAtEnd())
    2152                 :            :         {
    2153                 :          0 :             break;
    2154                 :            :         }
    2155         [ #  # ]:          0 :         pItem = aIter.NextItem();
    2156         [ #  # ]:          0 :     }
    2157                 :          0 : }
    2158                 :            : 
    2159                 :            : struct SfxItemSetClearer
    2160                 :            : {
    2161                 :            :     SfxItemSet & m_rItemSet;
    2162                 :        489 :     SfxItemSetClearer(SfxItemSet & rItemSet) : m_rItemSet(rItemSet) { }
    2163                 :          0 :     void operator()(sal_uInt16 const nWhich) { m_rItemSet.ClearItem(nWhich); }
    2164                 :            : };
    2165                 :            : 
    2166                 :            : }
    2167                 :            : 
    2168                 :            : 
    2169                 :            : /** Does the hard work of SwTxtNode::FmtToTxtAttr: the real conversion
    2170                 :            :     of items to automatic styles.
    2171                 :            :  */
    2172                 :            : void
    2173                 :       3933 : SwTxtNode::impl_FmtToTxtAttr(const SfxItemSet& i_rAttrSet)
    2174                 :            : {
    2175                 :            :     typedef AttrSpanMap_t::iterator AttrSpanMap_iterator_t;
    2176         [ +  - ]:       3933 :     AttrSpanMap_t aAttrSpanMap;
    2177                 :            : 
    2178         [ +  - ]:       3933 :     if (i_rAttrSet.Count() == 0)
    2179                 :            :     {
    2180                 :       3933 :         return;
    2181                 :            :     }
    2182                 :            : 
    2183                 :            :     // 1. Identify all spans in hints' array
    2184                 :            : 
    2185         [ #  # ]:          0 :     lcl_CollectHintSpans(*m_pSwpHints, m_Text.Len(), aAttrSpanMap);
    2186                 :            : 
    2187                 :            :     // 2. Go through all spans and insert new attrs
    2188                 :            : 
    2189                 :          0 :     AttrSpanMap_iterator_t aCurRange(aAttrSpanMap.begin());
    2190                 :          0 :     const AttrSpanMap_iterator_t aEnd(aAttrSpanMap.end());
    2191         [ #  # ]:          0 :     while (aCurRange != aEnd)
    2192                 :            :     {
    2193                 :            :         typedef std::pair<AttrSpanMap_iterator_t, AttrSpanMap_iterator_t>
    2194                 :            :             AttrSpanMapRange_t;
    2195         [ #  # ]:          0 :         AttrSpanMapRange_t aRange(aAttrSpanMap.equal_range(aCurRange->first));
    2196                 :            : 
    2197                 :            :         // 2a. Collect attributes to insert
    2198                 :            : 
    2199         [ #  # ]:          0 :         SfxItemSet aCurSet(i_rAttrSet);
    2200         [ #  # ]:          0 :         std::for_each(aRange.first, aRange.second, RemovePresentAttrs(aCurSet));
    2201                 :            : 
    2202                 :            :         // 2b. Insert automatic style containing the collected attributes
    2203                 :            : 
    2204         [ #  # ]:          0 :         if (aCurSet.Count() != 0)
    2205                 :            :         {
    2206                 :            :             AttrSpanMap_iterator_t aAutoStyleIt(
    2207         [ #  # ]:          0 :                     std::find_if(aRange.first, aRange.second, IsAutoStyle()));
    2208         [ #  # ]:          0 :             if (aAutoStyleIt != aRange.second)
    2209                 :            :             {
    2210                 :            :                 // there already is an automatic style on that span:
    2211                 :            :                 // create new one and remove the original one
    2212                 :          0 :                 SwTxtAttr* const pAutoStyle(const_cast<SwTxtAttr*>(aAutoStyleIt->second));
    2213                 :            :                 const boost::shared_ptr<SfxItemSet> pOldStyle(
    2214                 :            :                         static_cast<const SwFmtAutoFmt&>(
    2215         [ #  # ]:          0 :                             pAutoStyle->GetAttr()).GetStyleHandle());
    2216         [ #  # ]:          0 :                 aCurSet.Put(*pOldStyle);
    2217                 :            : 
    2218                 :            :                 // remove the old hint
    2219         [ #  # ]:          0 :                 m_pSwpHints->Delete(pAutoStyle);
    2220 [ #  # ][ #  # ]:          0 :                 DestroyAttr(pAutoStyle);
    2221                 :            :             }
    2222                 :            :             m_pSwpHints->Insert(
    2223                 :          0 :                     MakeTxtAttr(*GetDoc(), aCurSet,
    2224 [ #  # ][ #  # ]:          0 :                         aCurRange->first.first, aCurRange->first.second));
    2225                 :            :         }
    2226                 :            : 
    2227                 :          0 :         aCurRange = aRange.second;
    2228         [ #  # ]:          0 :     }
    2229                 :            : 
    2230                 :            :     // 3. Clear items from the node
    2231         [ #  # ]:          0 :     std::vector<sal_uInt16> aClearedIds;
    2232         [ #  # ]:          0 :     lcl_FillWhichIds(i_rAttrSet, aClearedIds);
    2233 [ #  # ][ -  + ]:       3933 :     ClearItemsFromAttrSet(aClearedIds);
    2234                 :            : }
    2235                 :            : 
    2236                 :       3933 : void SwTxtNode::FmtToTxtAttr( SwTxtNode* pNd )
    2237                 :            : {
    2238         [ +  - ]:       3933 :     SfxItemSet aThisSet( GetDoc()->GetAttrPool(), aCharFmtSetRange );
    2239 [ +  - ][ +  + ]:       3933 :     if( HasSwAttrSet() && GetpSwAttrSet()->Count() )
         [ +  - ][ +  - ]
                 [ +  + ]
    2240 [ +  - ][ +  - ]:         15 :         aThisSet.Put( *GetpSwAttrSet() );
    2241                 :            : 
    2242         [ +  - ]:       3933 :     GetOrCreateSwpHints();
    2243                 :            : 
    2244         [ +  + ]:       3933 :     if( pNd == this )
    2245                 :            :     {
    2246         [ +  - ]:       3444 :         impl_FmtToTxtAttr(aThisSet);
    2247                 :            :     }
    2248                 :            :     else
    2249                 :            :     {
    2250                 :            :         // There are five possible combinations of items from this and
    2251                 :            :         // pNd (pNd is the 'main' node):
    2252                 :            :         //
    2253                 :            :         //  case    pNd     this     action
    2254                 :            :         //  ----------------------------------------------------
    2255                 :            :         //     1     -       -      do nothing
    2256                 :            :         //     2     -       a      convert item to attr of this
    2257                 :            :         //     3     a       -      convert item to attr of pNd
    2258                 :            :         //     4     a       a      clear item in this
    2259                 :            :         //     5     a       b      convert item to attr of this
    2260                 :            : 
    2261         [ +  - ]:        489 :         SfxItemSet aNdSet( pNd->GetDoc()->GetAttrPool(), aCharFmtSetRange );
    2262 [ +  - ][ +  + ]:        489 :         if( pNd->HasSwAttrSet() && pNd->GetpSwAttrSet()->Count() )
         [ +  - ][ +  - ]
                 [ +  + ]
    2263 [ +  - ][ +  - ]:        342 :             aNdSet.Put( *pNd->GetpSwAttrSet() );
    2264                 :            : 
    2265         [ +  - ]:        489 :         pNd->GetOrCreateSwpHints();
    2266                 :            : 
    2267         [ +  - ]:        489 :         std::vector<sal_uInt16> aProcessedIds;
    2268                 :            : 
    2269         [ -  + ]:        489 :         if( aThisSet.Count() )
    2270                 :            :         {
    2271         [ #  # ]:          0 :             SfxItemIter aIter( aThisSet );
    2272                 :          0 :             const SfxPoolItem* pItem = aIter.GetCurItem(), *pNdItem = 0;
    2273         [ #  # ]:          0 :             SfxItemSet aConvertSet( GetDoc()->GetAttrPool(), aCharFmtSetRange );
    2274         [ #  # ]:          0 :             std::vector<sal_uInt16> aClearWhichIds;
    2275                 :            : 
    2276                 :          0 :             while( true )
    2277                 :            :             {
    2278 [ #  # ][ #  # ]:          0 :                 if( SFX_ITEM_SET == aNdSet.GetItemState( pItem->Which(), sal_False, &pNdItem ) )
    2279                 :            :                 {
    2280 [ #  # ][ #  # ]:          0 :                     if (*pItem == *pNdItem) // 4
    2281                 :            :                     {
    2282         [ #  # ]:          0 :                         aClearWhichIds.push_back( pItem->Which() );
    2283                 :            :                     }
    2284                 :            :                     else    // 5
    2285                 :            :                     {
    2286         [ #  # ]:          0 :                         aConvertSet.Put(*pItem);
    2287                 :            :                     }
    2288         [ #  # ]:          0 :                     aProcessedIds.push_back(pItem->Which());
    2289                 :            :                 }
    2290                 :            :                 else    // 2
    2291                 :            :                 {
    2292         [ #  # ]:          0 :                     aConvertSet.Put(*pItem);
    2293                 :            :                 }
    2294                 :            : 
    2295         [ #  # ]:          0 :                 if( aIter.IsAtEnd() )
    2296                 :          0 :                     break;
    2297         [ #  # ]:          0 :                 pItem = aIter.NextItem();
    2298                 :            :             }
    2299                 :            : 
    2300                 :            :             // 4/ clear items of this that are set with the same value on pNd
    2301         [ #  # ]:          0 :             ClearItemsFromAttrSet( aClearWhichIds );
    2302                 :            : 
    2303                 :            :             // 2, 5/ convert all other items to attrs
    2304 [ #  # ][ #  # ]:          0 :             impl_FmtToTxtAttr(aConvertSet);
                 [ #  # ]
    2305                 :            :         }
    2306                 :            : 
    2307                 :            :         {
    2308                 :            :             std::for_each(aProcessedIds.begin(), aProcessedIds.end(),
    2309         [ +  - ]:        489 :                     SfxItemSetClearer(aNdSet));
    2310                 :            : 
    2311                 :            :             // 3/ convert items to attrs
    2312         [ +  - ]:        489 :             pNd->impl_FmtToTxtAttr(aNdSet);
    2313                 :            : 
    2314         [ -  + ]:        489 :             if( aNdSet.Count() )
    2315                 :            :             {
    2316         [ #  # ]:          0 :                 SwFmtChg aTmp1( pNd->GetFmtColl() );
    2317 [ #  # ][ #  # ]:          0 :                 pNd->NotifyClients( &aTmp1, &aTmp1 );
    2318                 :            :             }
    2319         [ +  - ]:        489 :         }
    2320                 :            :     }
    2321                 :            : 
    2322                 :       3933 :     SetCalcHiddenCharFlags();
    2323                 :            : 
    2324 [ +  - ][ +  - ]:       3933 :     pNd->TryDeleteSwpHints();
    2325                 :       3933 : }
    2326                 :            : 
    2327                 :            : /*************************************************************************
    2328                 :            :  *                      SwpHints::CalcFlags()
    2329                 :            :  *************************************************************************/
    2330                 :            : 
    2331                 :      16694 : void SwpHints::CalcFlags()
    2332                 :            : {
    2333                 :      16694 :     m_bDDEFields = m_bFootnote = false;
    2334                 :      16694 :     const sal_uInt16 nSize = Count();
    2335                 :            :     const SwTxtAttr* pAttr;
    2336         [ +  + ]:     374840 :     for( sal_uInt16 nPos = 0; nPos < nSize; ++nPos )
    2337                 :            :     {
    2338      [ +  +  + ]:     358146 :         switch( ( pAttr = (*this)[ nPos ])->Which() )
    2339                 :            :         {
    2340                 :            :         case RES_TXTATR_FTN:
    2341                 :        120 :             m_bFootnote = true;
    2342         [ -  + ]:        120 :             if ( m_bDDEFields )
    2343                 :          0 :                 return;
    2344                 :        120 :             break;
    2345                 :            :         case RES_TXTATR_FIELD:
    2346                 :            :             {
    2347                 :     343634 :                 const SwField* pFld = pAttr->GetFld().GetFld();
    2348         [ -  + ]:     343634 :                 if( RES_DDEFLD == pFld->GetTyp()->Which() )
    2349                 :            :                 {
    2350                 :          0 :                     m_bDDEFields = true;
    2351         [ #  # ]:          0 :                     if ( m_bFootnote )
    2352                 :          0 :                         return;
    2353                 :            :                 }
    2354                 :            :             }
    2355                 :     343634 :             break;
    2356                 :            :         }
    2357                 :            :     }
    2358                 :            : }
    2359                 :            : 
    2360                 :            : /*************************************************************************
    2361                 :            :  *                      SwpHints::CalcVisibleFlag()
    2362                 :            :  *************************************************************************/
    2363                 :            : 
    2364                 :        268 : bool SwpHints::CalcHiddenParaField()
    2365                 :            : {
    2366                 :        268 :     m_bCalcHiddenParaField = false;
    2367                 :        268 :     bool bOldHasHiddenParaField = m_bHasHiddenParaField;
    2368                 :        268 :     bool bNewHasHiddenParaField  = false;
    2369                 :        268 :     const sal_uInt16    nSize = Count();
    2370                 :            :     const SwTxtAttr *pTxtHt;
    2371                 :            : 
    2372         [ +  + ]:        536 :     for( sal_uInt16 nPos = 0; nPos < nSize; ++nPos )
    2373                 :            :     {
    2374                 :        268 :         pTxtHt = (*this)[ nPos ];
    2375                 :        268 :         const sal_uInt16 nWhich = pTxtHt->Which();
    2376                 :            : 
    2377         [ +  - ]:        268 :         if( RES_TXTATR_FIELD == nWhich )
    2378                 :            :         {
    2379                 :        268 :             const SwFmtFld& rFld = pTxtHt->GetFld();
    2380         [ -  + ]:        268 :             if( RES_HIDDENPARAFLD == rFld.GetFld()->GetTyp()->Which() )
    2381                 :            :             {
    2382         [ #  # ]:          0 :                 if( !((SwHiddenParaField*)rFld.GetFld())->IsHidden() )
    2383                 :            :                 {
    2384                 :          0 :                     SetHiddenParaField(false);
    2385                 :          0 :                     return bOldHasHiddenParaField != bNewHasHiddenParaField;
    2386                 :            :                 }
    2387                 :            :                 else
    2388                 :            :                 {
    2389                 :          0 :                     bNewHasHiddenParaField = true;
    2390                 :            :                 }
    2391                 :            :             }
    2392                 :            :         }
    2393                 :            :     }
    2394                 :        268 :     SetHiddenParaField( bNewHasHiddenParaField );
    2395                 :        268 :     return bOldHasHiddenParaField != bNewHasHiddenParaField;
    2396                 :            : }
    2397                 :            : 
    2398                 :            : 
    2399                 :            : /*************************************************************************
    2400                 :            :  *                      SwpHints::NoteInHistory()
    2401                 :            :  *************************************************************************/
    2402                 :            : 
    2403                 :      32356 : void SwpHints::NoteInHistory( SwTxtAttr *pAttr, const bool bNew )
    2404                 :            : {
    2405         [ +  + ]:      32356 :     if ( m_pHistory ) { m_pHistory->AddHint( pAttr, bNew ); }
    2406                 :      32356 : }
    2407                 :            : 
    2408                 :            : /*************************************************************************
    2409                 :            :  *                      SwpHints::MergePortions( )
    2410                 :            :  *************************************************************************/
    2411                 :            : 
    2412                 :      13860 : bool SwpHints::MergePortions( SwTxtNode& rNode )
    2413                 :            : {
    2414         [ +  + ]:      13860 :     if ( !Count() )
    2415                 :          8 :         return false;
    2416                 :            : 
    2417                 :            :     // sort before merging
    2418         [ +  - ]:      13852 :     SwpHintsArray::Resort();
    2419                 :            : 
    2420                 :      13852 :     bool bRet = false;
    2421                 :            :     typedef std::multimap< int, SwTxtAttr* > PortionMap;
    2422         [ +  - ]:      13852 :     PortionMap aPortionMap;
    2423                 :      13852 :     xub_StrLen nLastPorStart = STRING_LEN;
    2424                 :      13852 :     sal_uInt16 i = 0;
    2425                 :      13852 :     int nKey = 0;
    2426                 :            : 
    2427                 :            :     // get portions by start position:
    2428         [ +  + ]:      57026 :     for ( i = 0; i < Count(); ++i )
    2429                 :            :     {
    2430         [ +  - ]:      43174 :         SwTxtAttr *pHt = GetTextHint( i );
    2431 [ +  - ][ +  + ]:      86232 :         if ( RES_TXTATR_CHARFMT != pHt->Which() &&
         [ +  + ][ +  + ]
    2432         [ +  - ]:      43058 :              RES_TXTATR_AUTOFMT != pHt->Which() )
    2433                 :            :              //&&
    2434                 :            :              //RES_TXTATR_INETFMT != pHt->Which() )
    2435                 :      17268 :             continue;
    2436                 :            : 
    2437                 :      25906 :         const xub_StrLen nPorStart = *pHt->GetStart();
    2438 [ +  + ][ +  + ]:      25906 :         if ( nPorStart != nLastPorStart && nLastPorStart != STRING_LEN )
    2439                 :      12081 :             ++nKey;
    2440                 :      25906 :         nLastPorStart = nPorStart;
    2441         [ +  - ]:      25906 :         aPortionMap.insert( std::pair< const int, SwTxtAttr* >( nKey, pHt ) );
    2442                 :            :     }
    2443                 :            : 
    2444                 :            :     // check if portion i can be merged with portion i+1:
    2445                 :      13852 :     i = 0;
    2446                 :      13852 :     int j = i + 1;
    2447         [ +  + ]:      40139 :     while ( i <= nKey )
    2448                 :            :     {
    2449         [ +  - ]:      26287 :         std::pair< PortionMap::iterator, PortionMap::iterator > aRange1 = aPortionMap.equal_range( i );
    2450         [ +  - ]:      26287 :         std::pair< PortionMap::iterator, PortionMap::iterator > aRange2 = aPortionMap.equal_range( j );
    2451                 :      26287 :         PortionMap::iterator aIter1 = aRange1.first;
    2452                 :      26287 :         PortionMap::iterator aIter2 = aRange2.first;
    2453                 :            : 
    2454                 :      26287 :         bool bMerge = true;
    2455         [ +  - ]:      26287 :         const sal_uInt16 nAttributesInPor1  = static_cast<sal_uInt16>(std::distance( aRange1.first, aRange1.second ));
    2456         [ +  - ]:      26287 :         const sal_uInt16 nAttributesInPor2  = static_cast<sal_uInt16>(std::distance( aRange2.first, aRange2.second ));
    2457                 :            : 
    2458 [ +  + ][ +  + ]:      26287 :         if ( nAttributesInPor1 == nAttributesInPor2 && nAttributesInPor1 != 0 )
    2459                 :            :         {
    2460         [ +  + ]:      12435 :             while ( aIter1 != aRange1.second )
    2461                 :            :             {
    2462                 :      12081 :                 const SwTxtAttr* p1 = (*aIter1).second;
    2463                 :      12081 :                 const SwTxtAttr* p2 = (*aIter2).second;
    2464 [ +  + ][ +  - ]:      12081 :                 if ( *p1->GetEnd() < *p2->GetStart() || p1->Which() != p2->Which() || !(*p1 == *p2) )
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
    2465                 :            :                 {
    2466                 :      11727 :                     bMerge = false;
    2467                 :      11727 :                     break;
    2468                 :            :                 }
    2469                 :        354 :                 ++aIter1;
    2470                 :        354 :                 ++aIter2;
    2471                 :      12081 :             }
    2472                 :            :         }
    2473                 :            :         else
    2474                 :            :         {
    2475                 :      14206 :             bMerge = false;
    2476                 :            :         }
    2477                 :            : 
    2478         [ +  + ]:      26287 :         if ( bMerge )
    2479                 :            :         {
    2480                 :            :             // erase all elements with key i + 1
    2481                 :        354 :             xub_StrLen nNewPortionEnd = 0;
    2482         [ +  + ]:        708 :             for ( aIter2 = aRange2.first; aIter2 != aRange2.second; ++aIter2 )
    2483                 :            :             {
    2484                 :        354 :                 SwTxtAttr* p2 = (*aIter2).second;
    2485         [ +  - ]:        354 :                 nNewPortionEnd = *p2->GetEnd();
    2486                 :            : 
    2487                 :        354 :                 const sal_uInt16 nCountBeforeDelete = Count();
    2488         [ +  - ]:        354 :                 Delete( p2 );
    2489                 :            : 
    2490                 :            :                 // robust: check if deletion actually took place before destroying attribute:
    2491         [ +  - ]:        354 :                 if ( Count() < nCountBeforeDelete )
    2492         [ +  - ]:        354 :                     rNode.DestroyAttr( p2 );
    2493                 :            :             }
    2494         [ +  - ]:        354 :             aPortionMap.erase( aRange2.first, aRange2.second );
    2495                 :        354 :             ++j;
    2496                 :            : 
    2497                 :            :             // change all attributes with key i
    2498         [ +  - ]:        354 :             aRange1 = aPortionMap.equal_range( i );
    2499         [ +  + ]:        708 :             for ( aIter1 = aRange1.first; aIter1 != aRange1.second; ++aIter1 )
    2500                 :            :             {
    2501                 :        354 :                 SwTxtAttr* p1 = (*aIter1).second;
    2502         [ +  - ]:        354 :                 NoteInHistory( p1 );
    2503         [ +  - ]:        354 :                 *p1->GetEnd() = nNewPortionEnd;
    2504         [ +  - ]:        354 :                 NoteInHistory( p1, true );
    2505                 :        354 :                 bRet = true;
    2506                 :            :             }
    2507                 :            :         }
    2508                 :            :         else
    2509                 :            :         {
    2510                 :      25933 :             ++i;
    2511                 :      26287 :             j = i + 1;
    2512                 :            :         }
    2513                 :            :     }
    2514                 :            : 
    2515         [ +  + ]:      13852 :     if ( bRet )
    2516                 :            :     {
    2517         [ +  - ]:        354 :         SwpHintsArray::Resort();
    2518                 :            :     }
    2519                 :            : 
    2520                 :      13860 :     return bRet;
    2521                 :            : }
    2522                 :            : 
    2523                 :            : // check if there is already a character format and adjust the sort numbers
    2524                 :          9 : void lcl_CheckSortNumber( const SwpHints& rHints, SwTxtCharFmt& rNewCharFmt )
    2525                 :            : {
    2526                 :          9 :     const xub_StrLen nHtStart = *rNewCharFmt.GetStart();
    2527                 :          9 :     const xub_StrLen nHtEnd   = *rNewCharFmt.GetEnd();
    2528                 :          9 :     sal_uInt16 nSortNumber = 0;
    2529                 :            : 
    2530         [ +  - ]:          9 :     for ( sal_uInt16 i = 0; i < rHints.Count(); ++i )
    2531                 :            :     {
    2532                 :          9 :         const SwTxtAttr* pOtherHt = rHints[i];
    2533                 :            : 
    2534                 :          9 :         const xub_StrLen nOtherStart = *pOtherHt->GetStart();
    2535                 :            : 
    2536         [ +  - ]:          9 :         if ( nOtherStart > nHtStart )
    2537                 :          9 :             break;
    2538                 :            : 
    2539         [ #  # ]:          0 :         if ( RES_TXTATR_CHARFMT == pOtherHt->Which() )
    2540                 :            :         {
    2541                 :          0 :             const xub_StrLen nOtherEnd = *pOtherHt->GetEnd();
    2542                 :            : 
    2543 [ #  # ][ #  # ]:          0 :             if ( nOtherStart == nHtStart && nOtherEnd == nHtEnd )
    2544                 :            :             {
    2545                 :          0 :                 const sal_uInt16 nOtherSortNum = static_cast<const SwTxtCharFmt*>(pOtherHt)->GetSortNumber();
    2546                 :          0 :                 nSortNumber = nOtherSortNum + 1;
    2547                 :            :             }
    2548                 :            :         }
    2549                 :            :     }
    2550                 :            : 
    2551         [ -  + ]:          9 :     if ( nSortNumber > 0 )
    2552                 :          0 :         rNewCharFmt.SetSortNumber( nSortNumber );
    2553                 :          9 : }
    2554                 :            : 
    2555                 :            : /*************************************************************************
    2556                 :            :  *                      SwpHints::Insert()
    2557                 :            :  *************************************************************************/
    2558                 :            : 
    2559                 :            : /*
    2560                 :            :  * Try to insert the new hint.
    2561                 :            :  * Depending on the type of the hint, this either always succeeds, or may fail.
    2562                 :            :  * Depending on the type of the hint, other hints may be deleted or
    2563                 :            :  * overwritten.
    2564                 :            :  * The return value indicates successful insertion.
    2565                 :            :  */
    2566                 :      19573 : bool SwpHints::TryInsertHint( SwTxtAttr* const pHint, SwTxtNode &rNode,
    2567                 :            :         const SetAttrMode nMode )
    2568                 :            : {
    2569         [ -  + ]:      19573 :     if ( USHRT_MAX == Count() ) // we're sorry, this flight is overbooked...
    2570                 :            :     {
    2571                 :            :         OSL_FAIL("hints array full :-(");
    2572                 :          0 :         return false;
    2573                 :            :     }
    2574                 :            : 
    2575                 :            :     // Felder bilden eine Ausnahme:
    2576                 :            :     // 1) Sie koennen nie ueberlappen
    2577                 :            :     // 2) Wenn zwei Felder genau aneinander liegen,
    2578                 :            :     //    sollen sie nicht zu einem verschmolzen werden.
    2579                 :            :     // Wir koennen also auf die while-Schleife verzichten
    2580                 :            : 
    2581                 :      19573 :     xub_StrLen *pHtEnd = pHint->GetEnd();
    2582                 :      19573 :     sal_uInt16 nWhich = pHint->Which();
    2583                 :            : 
    2584   [ +  +  +  +  :      19573 :     switch( nWhich )
          +  +  +  +  +  
                   -  + ]
    2585                 :            :     {
    2586                 :            :     case RES_TXTATR_CHARFMT:
    2587                 :            :     {
    2588                 :            :         // Check if character format contains hidden attribute:
    2589                 :         52 :         const SwCharFmt* pFmt = pHint->GetCharFmt().GetCharFmt();
    2590                 :            :         const SfxPoolItem* pItem;
    2591 [ -  + ][ +  - ]:         52 :         if ( SFX_ITEM_SET == pFmt->GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
    2592                 :          0 :             rNode.SetCalcHiddenCharFlags();
    2593                 :            : 
    2594                 :         52 :         ((SwTxtCharFmt*)pHint)->ChgTxtNode( &rNode );
    2595                 :            :         break;
    2596                 :            :     }
    2597                 :            :     // #i75430# Recalc hidden flags if necessary
    2598                 :            :     case RES_TXTATR_AUTOFMT:
    2599                 :            :     {
    2600                 :            :         // Check if auto style contains hidden attribute:
    2601                 :      16156 :         const SfxPoolItem* pHiddenItem = CharFmt::GetItem( *pHint, RES_CHRATR_HIDDEN );
    2602         [ +  + ]:      16156 :         if ( pHiddenItem )
    2603                 :         11 :             rNode.SetCalcHiddenCharFlags();
    2604                 :      16156 :         break;
    2605                 :            :     }
    2606                 :            :     case RES_TXTATR_INETFMT:
    2607                 :         89 :         static_cast<SwTxtINetFmt*>(pHint)->InitINetFmt(rNode);
    2608                 :         89 :         break;
    2609                 :            :     case RES_TXTATR_FIELD:
    2610                 :            :         {
    2611                 :       1549 :             sal_Bool bDelFirst = 0 != ((SwTxtFld*)pHint)->GetpTxtNode();
    2612                 :       1549 :             ((SwTxtFld*)pHint)->ChgTxtNode( &rNode );
    2613                 :       1549 :             SwDoc* pDoc = rNode.GetDoc();
    2614                 :       1549 :             const SwField* pFld = ((SwTxtFld*)pHint)->GetFld().GetFld();
    2615                 :            : 
    2616         [ +  + ]:       1549 :             if( !pDoc->IsNewFldLst() )
    2617                 :            :             {
    2618                 :            :                 // was fuer ein Feld ist es denn ??
    2619                 :            :                 // bestimmte Felder mussen am Doc das Calculations-Flag updaten
    2620      [ -  -  + ]:          4 :                 switch( pFld->GetTyp()->Which() )
    2621                 :            :                 {
    2622                 :            :                 case RES_DBFLD:
    2623                 :            :                 case RES_SETEXPFLD:
    2624                 :            :                 case RES_HIDDENPARAFLD:
    2625                 :            :                 case RES_HIDDENTXTFLD:
    2626                 :            :                 case RES_DBNUMSETFLD:
    2627                 :            :                 case RES_DBNEXTSETFLD:
    2628                 :            :                     {
    2629         [ #  # ]:          0 :                         if( bDelFirst )
    2630                 :          0 :                             pDoc->InsDelFldInFldLst( sal_False, *(SwTxtFld*)pHint );
    2631         [ #  # ]:          0 :                         if( rNode.GetNodes().IsDocNodes() )
    2632                 :          0 :                             pDoc->InsDelFldInFldLst( sal_True, *(SwTxtFld*)pHint );
    2633                 :            :                     }
    2634                 :          0 :                     break;
    2635                 :            :                 case RES_DDEFLD:
    2636         [ #  # ]:          0 :                     if( rNode.GetNodes().IsDocNodes() )
    2637                 :          0 :                         ((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt();
    2638                 :          4 :                     break;
    2639                 :            :                 }
    2640                 :            :             }
    2641                 :            : 
    2642                 :            :             // gehts ins normale Nodes-Array?
    2643         [ +  - ]:       1549 :             if( rNode.GetNodes().IsDocNodes() )
    2644                 :            :             {
    2645                 :       1549 :                 sal_Bool bInsFldType = sal_False;
    2646   [ +  -  -  +  :       1549 :                 switch( pFld->GetTyp()->Which() )
                      + ]
    2647                 :            :                 {
    2648                 :            :                 case RES_SETEXPFLD:
    2649                 :          3 :                     bInsFldType = ((SwSetExpFieldType*)pFld->GetTyp())->IsDeleted();
    2650         [ -  + ]:          3 :                     if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFld->GetTyp())->GetType() )
    2651                 :            :                     {
    2652                 :            :                         // bevor die ReferenzNummer gesetzt wird, sollte
    2653                 :            :                         // das Feld am richtigen FeldTypen haengen!
    2654                 :            :                         SwSetExpFieldType* pFldType = (SwSetExpFieldType*)
    2655                 :          0 :                                     pDoc->InsertFldType( *pFld->GetTyp() );
    2656         [ #  # ]:          0 :                         if( pFldType != pFld->GetTyp() )
    2657                 :            :                         {
    2658                 :            :                             SwFmtFld* pFmtFld = (SwFmtFld*)&((SwTxtFld*)pHint)
    2659                 :          0 :                                                                 ->GetFld();
    2660                 :          0 :                             pFmtFld->RegisterToFieldType( *pFldType );
    2661                 :          0 :                             pFmtFld->GetFld()->ChgTyp( pFldType );
    2662                 :            :                         }
    2663                 :          0 :                         pFldType->SetSeqRefNo( *(SwSetExpField*)pFld );
    2664                 :            :                     }
    2665                 :          3 :                     break;
    2666                 :            :                 case RES_USERFLD:
    2667                 :          0 :                     bInsFldType = ((SwUserFieldType*)pFld->GetTyp())->IsDeleted();
    2668                 :          0 :                     break;
    2669                 :            : 
    2670                 :            :                 case RES_DDEFLD:
    2671         [ #  # ]:          0 :                     if( pDoc->IsNewFldLst() )
    2672                 :          0 :                         ((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt();
    2673                 :          0 :                     bInsFldType = ((SwDDEFieldType*)pFld->GetTyp())->IsDeleted();
    2674                 :          0 :                     break;
    2675                 :            : 
    2676                 :            :                 case RES_POSTITFLD:
    2677         [ +  - ]:         27 :                     if ( pDoc->GetDocShell() )
    2678         [ +  - ]:         27 :                         pDoc->GetDocShell()->Broadcast( SwFmtFldHint( &((SwTxtFld*)pHint)->GetFld(), SWFMTFLD_INSERTED ) );
    2679                 :         27 :                     break;
    2680                 :            :                 }
    2681         [ -  + ]:       1549 :                 if( bInsFldType )
    2682                 :          0 :                     pDoc->InsDeletedFldType( *pFld->GetTyp() );
    2683                 :            :             }
    2684                 :            :         }
    2685                 :       1549 :         break;
    2686                 :            :     case RES_TXTATR_FTN :
    2687                 :         72 :         ((SwTxtFtn*)pHint)->ChgTxtNode( &rNode );
    2688                 :         72 :         break;
    2689                 :            :     case RES_TXTATR_REFMARK:
    2690                 :         83 :         ((SwTxtRefMark*)pHint)->ChgTxtNode( &rNode );
    2691         [ +  - ]:         83 :         if( rNode.GetNodes().IsDocNodes() )
    2692                 :            :         {
    2693                 :            :             // search for a reference with the same name
    2694                 :            :             SwTxtAttr* pTmpHt;
    2695                 :            :             xub_StrLen *pTmpHtEnd, *pTmpHintEnd;
    2696         [ +  + ]:        194 :             for( sal_uInt16 n = 0, nEnd = Count(); n < nEnd; ++n )
    2697                 :            :             {
    2698   [ +  +  -  + ]:        177 :                 if (RES_TXTATR_REFMARK == (pTmpHt = GetTextHint(n))->Which() &&
         [ #  # ][ #  # ]
                 [ -  + ]
    2699                 :         66 :                     pHint->GetAttr() == pTmpHt->GetAttr() &&
    2700                 :          0 :                     0 != ( pTmpHtEnd = pTmpHt->GetEnd() ) &&
    2701                 :          0 :                     0 != ( pTmpHintEnd = pHint->GetEnd() ) )
    2702                 :            :                 {
    2703                 :            :                     SwComparePosition eCmp = ::ComparePosition(
    2704                 :          0 :                             *pTmpHt->GetStart(), *pTmpHtEnd,
    2705                 :          0 :                             *pHint->GetStart(), *pTmpHintEnd );
    2706                 :          0 :                     sal_Bool bDelOld = sal_True, bChgStart = sal_False, bChgEnd = sal_False;
    2707   [ #  #  #  #  :          0 :                     switch( eCmp )
                      # ]
    2708                 :            :                     {
    2709                 :            :                     case POS_BEFORE:
    2710                 :          0 :                     case POS_BEHIND:    bDelOld = sal_False; break;
    2711                 :            : 
    2712                 :          0 :                     case POS_OUTSIDE:   bChgStart = bChgEnd = sal_True; break;
    2713                 :            : 
    2714                 :            :                     case POS_COLLIDE_END:
    2715                 :          0 :                     case POS_OVERLAP_BEFORE:    bChgStart = sal_True; break;
    2716                 :            :                     case POS_COLLIDE_START:
    2717                 :          0 :                     case POS_OVERLAP_BEHIND:    bChgEnd = sal_True; break;
    2718                 :          0 :                     default: break;
    2719                 :            :                     }
    2720                 :            : 
    2721         [ #  # ]:          0 :                     if( bChgStart )
    2722                 :          0 :                         *pHint->GetStart() = *pTmpHt->GetStart();
    2723         [ #  # ]:          0 :                     if( bChgEnd )
    2724                 :          0 :                         *pTmpHintEnd = *pTmpHtEnd;
    2725                 :            : 
    2726         [ #  # ]:          0 :                     if( bDelOld )
    2727                 :            :                     {
    2728                 :          0 :                         NoteInHistory( pTmpHt );
    2729                 :          0 :                         rNode.DestroyAttr( Cut( n-- ) );
    2730                 :          0 :                         --nEnd;
    2731                 :            :                     }
    2732                 :            :                 }
    2733                 :            :             }
    2734                 :            :         }
    2735                 :         83 :         break;
    2736                 :            :     case RES_TXTATR_TOXMARK:
    2737                 :         78 :         ((SwTxtTOXMark*)pHint)->ChgTxtNode( &rNode );
    2738                 :         78 :         break;
    2739                 :            : 
    2740                 :            :     case RES_TXTATR_CJK_RUBY:
    2741                 :        330 :         static_cast<SwTxtRuby*>(pHint)->InitRuby(rNode);
    2742                 :        330 :         break;
    2743                 :            : 
    2744                 :            :     case RES_TXTATR_META:
    2745                 :            :     case RES_TXTATR_METAFIELD:
    2746                 :        194 :         static_cast<SwTxtMeta *>(pHint)->ChgTxtNode( &rNode );
    2747                 :        194 :         break;
    2748                 :            : 
    2749                 :            :     case RES_CHRATR_HIDDEN:
    2750                 :          0 :         rNode.SetCalcHiddenCharFlags();
    2751                 :          0 :         break;
    2752                 :            :     }
    2753                 :            : 
    2754         [ +  + ]:      19573 :     if( nsSetAttrMode::SETATTR_DONTEXPAND & nMode )
    2755                 :        352 :         pHint->SetDontExpand( sal_True );
    2756                 :            : 
    2757                 :            :     // SwTxtAttrs ohne Ende werden sonderbehandelt:
    2758                 :            :     // Sie werden natuerlich in das Array insertet, aber sie werden nicht
    2759                 :            :     // in die pPrev/Next/On/Off-Verkettung aufgenommen.
    2760                 :            :     // Der Formatierer erkennt diese TxtHints an dem CH_TXTATR_.. im Text !
    2761                 :      19573 :     xub_StrLen nHtStart = *pHint->GetStart();
    2762         [ +  + ]:      19573 :     if( !pHtEnd )
    2763                 :            :     {
    2764                 :       2696 :         SwpHintsArray::Insert( pHint );
    2765                 :       2696 :         CalcFlags();
    2766                 :            : #ifdef DBG_UTIL
    2767                 :            :         if( !rNode.GetDoc()->IsInReading() )
    2768                 :            :             CHECK;
    2769                 :            : #endif
    2770                 :            :         // ... und die Abhaengigen benachrichtigen
    2771         [ +  + ]:       2696 :         if ( rNode.GetDepends() )
    2772                 :            :         {
    2773         [ +  - ]:       2195 :             SwUpdateAttr aHint( nHtStart, nHtStart, nWhich );
    2774 [ +  - ][ +  - ]:       2195 :             rNode.ModifyNotification( 0, &aHint );
    2775                 :            :         }
    2776                 :       2696 :         return true;
    2777                 :            :     }
    2778                 :            : 
    2779                 :            :     // ----------------------------------------------------------------
    2780                 :            :     // Ab hier gibt es nur noch pHint mit einem EndIdx !!!
    2781                 :            : 
    2782         [ -  + ]:      16877 :     if( *pHtEnd < nHtStart )
    2783                 :            :     {
    2784                 :            :         OSL_ENSURE( *pHtEnd >= nHtStart,
    2785                 :            :                     "+SwpHints::Insert: invalid hint, end < start" );
    2786                 :            : 
    2787                 :            :         // Wir drehen den Quatsch einfach um:
    2788                 :          0 :         *pHint->GetStart() = *pHtEnd;
    2789                 :          0 :         *pHtEnd = nHtStart;
    2790                 :          0 :         nHtStart = *pHint->GetStart();
    2791                 :            :     }
    2792                 :            : 
    2793                 :            :     // I need this value later on for notification but the pointer may become invalid
    2794                 :      16877 :     const xub_StrLen nHintEnd = *pHtEnd;
    2795                 :      16877 :     const bool bNoHintAdjustMode = (nsSetAttrMode::SETATTR_NOHINTADJUST & nMode);
    2796                 :            : 
    2797                 :            :     // handle nesting attributes: inserting may fail due to overlap!
    2798         [ +  + ]:      16877 :     if (pHint->IsNesting())
    2799                 :            :     {
    2800                 :            :         const bool bRet(
    2801                 :        613 :             TryInsertNesting(rNode, *static_cast<SwTxtAttrNesting*>(pHint)));
    2802         [ +  + ]:        613 :         if (!bRet) return false;
    2803                 :            :     }
    2804                 :            :     // Currently REFMARK and TOXMARK have OverlapAllowed set to true.
    2805                 :            :     // These attributes may be inserted directly.
    2806                 :            :     // Also attributes without length may be inserted directly.
    2807                 :            :     // SETATTR_NOHINTADJUST is set e.g., during undo.
    2808                 :            :     // Portion building in not necessary during XML import.
    2809                 :            :     else
    2810   [ +  +  +  +  :      46014 :     if ( !bNoHintAdjustMode &&
           +  + ][ +  + ]
         [ +  - ][ +  + ]
    2811                 :      14903 :          !pHint->IsOverlapAllowedAttr() &&
    2812                 :      14847 :          !rNode.GetDoc()->IsInXMLImport() &&
    2813                 :            :          ( RES_TXTATR_AUTOFMT == nWhich ||
    2814                 :            :            RES_TXTATR_CHARFMT == nWhich ) )
    2815                 :            :     {
    2816                 :            :         OSL_ENSURE( nWhich != RES_TXTATR_AUTOFMT ||
    2817                 :            :                 static_cast<const SwFmtAutoFmt&>(pHint->GetAttr()).GetStyleHandle()->GetPool() ==
    2818                 :            :                 &rNode.GetDoc()->GetAttrPool(),
    2819                 :            :                 "AUTOSTYLES - Pool mismatch" );
    2820                 :            : 
    2821                 :      14834 :         BuildPortions( rNode, *pHint, nMode );
    2822                 :            : 
    2823         [ +  + ]:      14834 :         if ( nHtStart < nHintEnd ) // skip merging for 0-length attributes
    2824                 :      12918 :             MergePortions( rNode );
    2825                 :            :     }
    2826                 :            :     else
    2827                 :            :     {
    2828                 :            :         // There may be more than one character style at the current position.
    2829                 :            :         // Take care of the sort number.
    2830                 :            :         // Special case ruby portion: During import, the ruby attribute is set
    2831                 :            :         // multiple times
    2832                 :            :         // Special case hyperlink: During import, the ruby attribute is set
    2833                 :            :         // multiple times
    2834                 :            :         // FME 2007-11-08 #i82989# in NOHINTADJUST mode, we want to insert
    2835                 :            :         // character attributes directly
    2836 [ +  + ][ -  + ]:       1430 :         if ( ( RES_TXTATR_CHARFMT  == nWhich && !bNoHintAdjustMode ) )
    2837                 :            :         {
    2838                 :          0 :             BuildPortions( rNode, *pHint, nMode );
    2839                 :            :         }
    2840                 :            :         else
    2841                 :            :         {
    2842                 :            :             // #i82989# Check sort numbers in NoHintAdjustMode
    2843         [ +  + ]:       1430 :             if ( RES_TXTATR_CHARFMT == nWhich )
    2844                 :          9 :                 lcl_CheckSortNumber( *this, *static_cast<SwTxtCharFmt*>(pHint) );
    2845                 :            : 
    2846                 :       1430 :             SwpHintsArray::Insert( pHint );
    2847                 :       1430 :             NoteInHistory( pHint, true );
    2848                 :            :         }
    2849                 :            :     }
    2850                 :            : 
    2851                 :            :     // ... und die Abhaengigen benachrichtigen
    2852         [ +  + ]:      16873 :     if ( rNode.GetDepends() )
    2853                 :            :     {
    2854 [ +  + ][ +  - ]:       8848 :         SwUpdateAttr aHint( nHtStart, nHtStart == nHintEnd ? nHintEnd + 1 : nHintEnd, nWhich );
    2855 [ +  - ][ +  - ]:       8848 :         rNode.ModifyNotification( 0, &aHint );
    2856                 :            :     }
    2857                 :            : 
    2858                 :            : #ifdef DBG_UTIL
    2859                 :            :     if( !bNoHintAdjustMode && !rNode.GetDoc()->IsInReading() )
    2860                 :            :         CHECK;
    2861                 :            : #endif
    2862                 :            : 
    2863                 :      19573 :     return true;
    2864                 :            : }
    2865                 :            : 
    2866                 :            : /*************************************************************************
    2867                 :            :  *                      SwpHints::DeleteAtPos()
    2868                 :            :  *************************************************************************/
    2869                 :            : 
    2870                 :      13998 : void SwpHints::DeleteAtPos( const sal_uInt16 nPos )
    2871                 :            : {
    2872                 :      13998 :     SwTxtAttr *pHint = GetTextHint(nPos);
    2873                 :            :     // ChainDelete( pHint );
    2874                 :      13998 :     NoteInHistory( pHint );
    2875                 :      13998 :     SwpHintsArray::DeleteAtPos( nPos );
    2876                 :            : 
    2877         [ +  + ]:      13998 :     if( RES_TXTATR_FIELD == pHint->Which() )
    2878                 :            :     {
    2879                 :         38 :         SwFieldType* pFldTyp = ((SwTxtFld*)pHint)->GetFld().GetFld()->GetTyp();
    2880         [ -  + ]:         38 :         if( RES_DDEFLD == pFldTyp->Which() )
    2881                 :            :         {
    2882                 :          0 :             const SwTxtNode* pNd = ((SwTxtFld*)pHint)->GetpTxtNode();
    2883 [ #  # ][ #  # ]:          0 :             if( pNd && pNd->GetNodes().IsDocNodes() )
                 [ #  # ]
    2884                 :          0 :                 ((SwDDEFieldType*)pFldTyp)->DecRefCnt();
    2885                 :          0 :             ((SwTxtFld*)pHint)->ChgTxtNode( 0 );
    2886                 :            :         }
    2887         [ +  + ]:         38 :         else if( RES_POSTITFLD == pFldTyp->Which() )
    2888                 :            :         {
    2889         [ +  - ]:          6 :             const_cast<SwFmtFld&>(((SwTxtFld*)pHint)->GetFld()).Broadcast( SwFmtFldHint( &((SwTxtFld*)pHint)->GetFld(), SWFMTFLD_REMOVED ) );
    2890                 :            :         }
    2891   [ -  +  #  # ]:         32 :         else if ( m_bHasHiddenParaField &&
                 [ -  + ]
    2892                 :          0 :                  RES_HIDDENPARAFLD == pFldTyp->Which() )
    2893                 :            :         {
    2894                 :          0 :             m_bCalcHiddenParaField = true;
    2895                 :            :         }
    2896                 :            :     }
    2897                 :            : 
    2898                 :      13998 :     CalcFlags();
    2899                 :            :     CHECK;
    2900                 :      13998 : }
    2901                 :            : 
    2902                 :            : // Ist der Hint schon bekannt, dann suche die Position und loesche ihn.
    2903                 :            : // Ist er nicht im Array, so gibt es ein OSL_ENSURE(!!
    2904                 :            : 
    2905                 :      11480 : void SwpHints::Delete( SwTxtAttr* pTxtHt )
    2906                 :            : {
    2907                 :            :     // Attr 2.0: SwpHintsArr::Delete( pTxtHt );
    2908                 :      11480 :     const sal_uInt16 nPos = GetStartOf( pTxtHt );
    2909                 :            :     OSL_ENSURE( USHRT_MAX != nPos, "Attribut nicht im Attribut-Array!" );
    2910         [ +  - ]:      11480 :     if( USHRT_MAX != nPos )
    2911                 :      11480 :         DeleteAtPos( nPos );
    2912                 :      11480 : }
    2913                 :            : 
    2914                 :          0 : void SwTxtNode::ClearSwpHintsArr( bool bDelFields )
    2915                 :            : {
    2916         [ #  # ]:          0 :     if ( HasHints() )
    2917                 :            :     {
    2918                 :          0 :         sal_uInt16 nPos = 0;
    2919         [ #  # ]:          0 :         while ( nPos < m_pSwpHints->Count() )
    2920                 :            :         {
    2921                 :          0 :             SwTxtAttr* pDel = m_pSwpHints->GetTextHint( nPos );
    2922                 :          0 :             bool bDel = false;
    2923                 :            : 
    2924      [ #  #  # ]:          0 :             switch( pDel->Which() )
    2925                 :            :             {
    2926                 :            :             case RES_TXTATR_FLYCNT:
    2927                 :            :             case RES_TXTATR_FTN:
    2928                 :          0 :                 break;
    2929                 :            : 
    2930                 :            :             case RES_TXTATR_FIELD:
    2931         [ #  # ]:          0 :                 if( bDelFields )
    2932                 :          0 :                     bDel = true;
    2933                 :          0 :                 break;
    2934                 :            :             default:
    2935                 :          0 :                 bDel = true; break;
    2936                 :            :             }
    2937                 :            : 
    2938         [ #  # ]:          0 :             if( bDel )
    2939                 :            :             {
    2940                 :          0 :                 m_pSwpHints->SwpHintsArray::DeleteAtPos( nPos );
    2941                 :          0 :                 DestroyAttr( pDel );
    2942                 :            :             }
    2943                 :            :             else
    2944                 :          0 :                 ++nPos;
    2945                 :            :         }
    2946                 :            :     }
    2947                 :          0 : }
    2948                 :            : 
    2949                 :     287207 : sal_uInt16 SwTxtNode::GetLang( const xub_StrLen nBegin, const xub_StrLen nLen,
    2950                 :            :                            sal_uInt16 nScript ) const
    2951                 :            : {
    2952                 :     287207 :     sal_uInt16 nRet = LANGUAGE_DONTKNOW;
    2953                 :            : 
    2954         [ +  + ]:     287207 :     if ( ! nScript )
    2955                 :            :     {
    2956         [ +  - ]:     184306 :         nScript = pBreakIt->GetRealScriptOfText( m_Text, nBegin );
    2957                 :            :     }
    2958                 :            : 
    2959                 :            :     // #i91465# Consider nScript if pSwpHints == 0
    2960                 :     287207 :     const sal_uInt16 nWhichId = GetWhichOfScript( RES_CHRATR_LANGUAGE, nScript );
    2961                 :            : 
    2962         [ +  + ]:     287207 :     if ( HasHints() )
    2963                 :            :     {
    2964                 :      10382 :         const xub_StrLen nEnd = nBegin + nLen;
    2965         [ +  + ]:      33348 :         for ( sal_uInt16 i = 0, nSize = m_pSwpHints->Count(); i < nSize; ++i )
    2966                 :            :         {
    2967                 :            :             // ist der Attribut-Anfang schon groesser als der Idx ?
    2968                 :      22966 :             const SwTxtAttr *pHt = m_pSwpHints->operator[](i);
    2969                 :      22966 :             const xub_StrLen nAttrStart = *pHt->GetStart();
    2970         [ +  + ]:      22966 :             if( nEnd < nAttrStart )
    2971                 :       2699 :                 break;
    2972                 :            : 
    2973                 :      20267 :             const sal_uInt16 nWhich = pHt->Which();
    2974                 :            : 
    2975   [ +  +  +  + ]:      43762 :             if( nWhichId == nWhich ||
                 [ +  + ]
           [ +  -  +  + ]
    2976                 :      23495 :                     ( ( pHt->IsCharFmtAttr() || RES_TXTATR_AUTOFMT == nWhich ) && CharFmt::IsItemIncluded( nWhichId, pHt ) ) )
    2977                 :            :             {
    2978                 :       1473 :                 const xub_StrLen *pEndIdx = pHt->GetEnd();
    2979                 :            :                 // Ueberlappt das Attribut den Bereich?
    2980                 :            : 
    2981 [ +  + ][ +  + ]:       2465 :                 if( pEndIdx &&
                 [ +  + ]
           [ +  +  +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  - ]
    2982                 :            :                     nLen ? ( nAttrStart < nEnd && nBegin < *pEndIdx )
    2983                 :            :                          : (( nAttrStart < nBegin &&
    2984                 :        992 :                                 ( pHt->DontExpand() ? nBegin < *pEndIdx
    2985                 :            :                                                     : nBegin <= *pEndIdx )) ||
    2986                 :            :                             ( nBegin == nAttrStart &&
    2987                 :            :                                 ( nAttrStart == *pEndIdx || !nBegin ))) )
    2988                 :            :                 {
    2989                 :        718 :                     const SfxPoolItem* pItem = CharFmt::GetItem( *pHt, nWhichId );
    2990                 :        718 :                     sal_uInt16 nLng = ((SvxLanguageItem*)pItem)->GetLanguage();
    2991                 :            : 
    2992                 :            :                     // Umfasst das Attribut den Bereich komplett?
    2993 [ +  - ][ +  - ]:        718 :                     if( nAttrStart <= nBegin && nEnd <= *pEndIdx )
    2994                 :        718 :                         nRet = nLng;
    2995         [ #  # ]:          0 :                     else if( LANGUAGE_DONTKNOW == nRet )
    2996                 :        718 :                         nRet = nLng; // partielle Ueberlappung, der 1. gewinnt
    2997                 :            :                 }
    2998                 :            :             }
    2999                 :            :         }
    3000                 :            :     }
    3001         [ +  + ]:     287207 :     if( LANGUAGE_DONTKNOW == nRet )
    3002                 :            :     {
    3003                 :     286489 :         nRet = ((SvxLanguageItem&)GetSwAttrSet().Get( nWhichId )).GetLanguage();
    3004         [ -  + ]:     286489 :         if( LANGUAGE_DONTKNOW == nRet )
    3005                 :          0 :             nRet = static_cast<sal_uInt16>(GetAppLanguage());
    3006                 :            :     }
    3007                 :     287207 :     return nRet;
    3008                 :            : }
    3009                 :            : 
    3010                 :            : 
    3011                 :       2887 : sal_Unicode GetCharOfTxtAttr( const SwTxtAttr& rAttr )
    3012                 :            : {
    3013                 :       2887 :     sal_Unicode cRet = CH_TXTATR_BREAKWORD;
    3014      [ +  +  - ]:       2887 :     switch ( rAttr.Which() )
    3015                 :            :     {
    3016                 :            :         case RES_TXTATR_REFMARK:
    3017                 :            :         case RES_TXTATR_TOXMARK:
    3018                 :        105 :             cRet = CH_TXTATR_INWORD;
    3019                 :        105 :         break;
    3020                 :            : 
    3021                 :            :         case RES_TXTATR_FIELD:
    3022                 :            :         case RES_TXTATR_FLYCNT:
    3023                 :            :         case RES_TXTATR_FTN:
    3024                 :            :         case RES_TXTATR_META:
    3025                 :            :         case RES_TXTATR_METAFIELD:
    3026                 :            :         {
    3027                 :       2782 :             cRet = CH_TXTATR_BREAKWORD;
    3028                 :            : 
    3029                 :            :             // #i78149: PostIt fields should not break words for spell and grammar checking
    3030   [ +  +  +  + ]:       4331 :             if (rAttr.Which() == RES_TXTATR_FIELD &&
                 [ +  + ]
    3031                 :       1549 :                 RES_POSTITFLD == rAttr.GetFld().GetFld()->GetTyp()->Which())
    3032                 :         27 :                 cRet = CH_TXTATR_INWORD;
    3033                 :            :         }
    3034                 :       2782 :         break;
    3035                 :            : 
    3036                 :            :         default:
    3037                 :            :             OSL_FAIL("GetCharOfTxtAttr: unknown attr");
    3038                 :          0 :             break;
    3039                 :            :     }
    3040                 :       2887 :     return cRet;
    3041                 :            : }
    3042                 :            : 
    3043                 :            : 
    3044                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10