LCOV - code coverage report
Current view: top level - sw/source/core/txtnode - thints.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1206 1459 82.7 %
Date: 2014-11-03 Functions: 55 57 96.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <hintids.hxx>
      21             : #include <sot/factory.hxx>
      22             : #include <editeng/xmlcnitm.hxx>
      23             : #include <svl/whiter.hxx>
      24             : #include <svl/itemiter.hxx>
      25             : #include <svl/stylepool.hxx>
      26             : #include <editeng/fontitem.hxx>
      27             : #include <editeng/langitem.hxx>
      28             : #include <editeng/emphasismarkitem.hxx>
      29             : #include <editeng/charscaleitem.hxx>
      30             : #include <editeng/charrotateitem.hxx>
      31             : #include <editeng/lrspitem.hxx>
      32             : #include <txtinet.hxx>
      33             : #include <txtflcnt.hxx>
      34             : #include <fmtfld.hxx>
      35             : #include <fmtrfmrk.hxx>
      36             : #include <fmtanchr.hxx>
      37             : #include <fmtinfmt.hxx>
      38             : #include <txtatr.hxx>
      39             : #include <fchrfmt.hxx>
      40             : #include <fmtautofmt.hxx>
      41             : #include <fmtflcnt.hxx>
      42             : #include <fmtftn.hxx>
      43             : #include <txttxmrk.hxx>
      44             : #include <txtrfmrk.hxx>
      45             : #include <txtftn.hxx>
      46             : #include <txtfld.hxx>
      47             : #include <txtannotationfld.hxx>
      48             : #include <charatr.hxx>
      49             : #include <charfmt.hxx>
      50             : #include <frmfmt.hxx>
      51             : #include <ftnidx.hxx>
      52             : #include <fmtruby.hxx>
      53             : #include <fmtmeta.hxx>
      54             : #include <breakit.hxx>
      55             : #include <doc.hxx>
      56             : #include <IDocumentUndoRedo.hxx>
      57             : #include <IDocumentFieldsAccess.hxx>
      58             : #include <IDocumentLayoutAccess.hxx>
      59             : #include <IDocumentStylePoolAccess.hxx>
      60             : #include <fldbas.hxx>
      61             : #include <pam.hxx>
      62             : #include <ndtxt.hxx>
      63             : #include <txtfrm.hxx>
      64             : #include <rolbck.hxx>
      65             : #include <ddefld.hxx>
      66             : #include <docufld.hxx>
      67             : #include <expfld.hxx>
      68             : #include <usrfld.hxx>
      69             : #include <poolfmt.hxx>
      70             : #include <swfont.hxx>
      71             : #include <istyleaccess.hxx>
      72             : #include <dcontact.hxx>
      73             : #include <docsh.hxx>
      74             : #include <svl/smplhint.hxx>
      75             : #include <algorithm>
      76             : #include <map>
      77             : #include <boost/scoped_ptr.hpp>
      78             : 
      79             : #ifdef DBG_UTIL
      80             : #define CHECK           Check(true);
      81             : #define CHECK_NOTMERGED Check(false);
      82             : #else
      83             : #define CHECK_NOTMERGED
      84             : #endif
      85             : 
      86             : using namespace ::com::sun::star::i18n;
      87             : 
      88      129230 : SwpHints::SwpHints()
      89             :     : m_pHistory(0)
      90             :     , m_bFontChange(true)
      91             :     , m_bInSplitNode(false)
      92             :     , m_bCalcHiddenParaField(false)
      93             :     , m_bHasHiddenParaField(false)
      94             :     , m_bFootnote(false)
      95      129230 :     , m_bDDEFields(false)
      96             : {
      97      129230 : }
      98             : 
      99             : struct TxtAttrDeleter
     100             : {
     101             :     SwAttrPool & m_rPool;
     102           4 :     TxtAttrDeleter( SwDoc & rDoc ) : m_rPool( rDoc.GetAttrPool() ) { }
     103           4 :     void operator() (SwTxtAttr * const pAttr)
     104             :     {
     105           4 :         if (RES_TXTATR_META == pAttr->Which() ||
     106           0 :             RES_TXTATR_METAFIELD == pAttr->Which())
     107             :         {
     108           4 :             static_txtattr_cast<SwTxtMeta *>(pAttr)->ChgTxtNode(0); // prevents ASSERT
     109             :         }
     110           4 :         SwTxtAttr::Destroy( pAttr, m_rPool );
     111           4 :     }
     112             : };
     113             : 
     114             : struct TxtAttrContains
     115             : {
     116             :     sal_Int32 m_nPos;
     117          60 :     TxtAttrContains( const sal_Int32 nPos ) : m_nPos( nPos ) { }
     118          78 :     bool operator() (SwTxtAttrEnd * const pAttr)
     119             :     {
     120          78 :         return (pAttr->GetStart() < m_nPos) && (m_nPos < *pAttr->End());
     121             :     }
     122             : };
     123             : 
     124             : // a:       |-----|
     125             : // b:
     126             : //    |---|               => valid: b before a
     127             : //    |-----|             => valid: start == end; b before a
     128             : //    |---------|         => invalid: overlap (1)
     129             : //    |-----------|       => valid: same end; b around a
     130             : //    |-----------------| => valid: b around a
     131             : //          |---|         => valid; same start; b within a
     132             : //          |-----|       => valid; same start and end; b around or within a?
     133             : //          |-----------| => valid: same start: b around a
     134             : //            |-|         => valid: b within a
     135             : //            |---|       => valid: same end; b within a
     136             : //            |---------| => invalid: overlap (2)
     137             : //                |-----| => valid: end == start; b after a
     138             : //                  |---| => valid: b after a
     139             : // ===> 2 invalid overlap cases
     140             : static
     141        4034 : bool isOverlap(const sal_Int32 nStart1, const sal_Int32 nEnd1,
     142             :                const sal_Int32 nStart2, const sal_Int32 nEnd2)
     143             : {
     144             :     return
     145        3592 :         ((nStart1 > nStart2) && (nStart1 < nEnd2) && (nEnd1 > nEnd2))  // (1)
     146        8018 :      || ((nStart1 < nStart2) && (nStart2 < nEnd1) && (nEnd1 < nEnd2)); // (2)
     147             : }
     148             : 
     149             : /// #i106930#: now asymmetric: empty hint1 is _not_ nested, but empty hint2 is
     150             : static
     151        3948 : bool isNestedAny(const sal_Int32 nStart1, const sal_Int32 nEnd1,
     152             :                  const sal_Int32 nStart2, const sal_Int32 nEnd2)
     153             : {
     154        3696 :     return ((nStart1 == nStart2) || (nEnd1 == nEnd2))
     155             :         // same start/end: nested except if hint1 empty and hint2 not empty
     156         324 :         ? (nStart1 != nEnd1) || (nStart2 == nEnd2)
     157        4272 :         : ((nStart1 < nStart2) ? (nEnd1 >= nEnd2) : (nEnd1 <= nEnd2));
     158             : }
     159             : 
     160             : static
     161        3402 : bool isSelfNestable(const sal_uInt16 nWhich)
     162             : {
     163        3402 :     if ((RES_TXTATR_INETFMT  == nWhich) ||
     164         222 :         (RES_TXTATR_CJK_RUBY == nWhich) ||
     165             :         (RES_TXTATR_INPUTFIELD == nWhich))
     166        3208 :         return false;
     167             :     assert((RES_TXTATR_META  == nWhich) ||
     168             :            (RES_TXTATR_METAFIELD  == nWhich));
     169         194 :     return true;
     170             : }
     171             : 
     172             : static
     173         144 : bool isSplittable(const sal_uInt16 nWhich)
     174             : {
     175         144 :     if ((RES_TXTATR_INETFMT  == nWhich) ||
     176             :         (RES_TXTATR_CJK_RUBY == nWhich))
     177          82 :         return true;
     178             :     assert((RES_TXTATR_META  == nWhich) ||
     179             :            (RES_TXTATR_METAFIELD  == nWhich) ||
     180             :            (RES_TXTATR_INPUTFIELD  == nWhich));
     181          62 :     return false;
     182             : }
     183             : 
     184             : enum Split_t { FAIL, SPLIT_NEW, SPLIT_OTHER };
     185             : /**
     186             :   Calculate splitting policy for overlapping hints, based on what kind of
     187             :   hint is inserted, and what kind of existing hint overlaps.
     188             :   */
     189             : static Split_t
     190          86 : splitPolicy(const sal_uInt16 nWhichNew, const sal_uInt16 nWhichOther)
     191             : {
     192          86 :     if (!isSplittable(nWhichOther))
     193             :     {
     194          58 :         if (!isSplittable(nWhichNew))
     195           4 :             return FAIL;
     196             :         else
     197          54 :             return SPLIT_NEW;
     198             :     }
     199             :     else
     200             :     {
     201          28 :         if ( RES_TXTATR_INPUTFIELD == nWhichNew )
     202           0 :             return FAIL;
     203          28 :         else if ( (RES_TXTATR_INETFMT  == nWhichNew) &&
     204             :                   (RES_TXTATR_CJK_RUBY == nWhichOther) )
     205           6 :             return SPLIT_NEW;
     206             :         else
     207          22 :             return SPLIT_OTHER;
     208             :     }
     209             : }
     210             : 
     211        2870 : void SwTxtINetFmt::InitINetFmt(SwTxtNode & rNode)
     212             : {
     213        2870 :     ChgTxtNode(&rNode);
     214             :     SwCharFmt * const pFmt(
     215        2870 :          rNode.GetDoc()->getIDocumentStylePoolAccess().GetCharFmtFromPool(RES_POOLCHR_INET_NORMAL) );
     216        2870 :     pFmt->Add( this );
     217        2870 : }
     218             : 
     219         362 : void SwTxtRuby::InitRuby(SwTxtNode & rNode)
     220             : {
     221         362 :     ChgTxtNode(&rNode);
     222             :     SwCharFmt * const pFmt(
     223         362 :         rNode.GetDoc()->getIDocumentStylePoolAccess().GetCharFmtFromPool(RES_POOLCHR_RUBYTEXT) );
     224         362 :     pFmt->Add( this );
     225         362 : }
     226             : 
     227             : /**
     228             :   Create a new nesting text hint.
     229             :  */
     230             : static SwTxtAttrNesting *
     231          84 : MakeTxtAttrNesting(SwTxtNode & rNode, SwTxtAttrNesting & rNesting,
     232             :         const sal_Int32 nStart, const sal_Int32 nEnd)
     233             : {
     234             :     SwTxtAttr * const pNew( MakeTxtAttr(
     235          84 :             *rNode.GetDoc(), rNesting.GetAttr(), nStart, nEnd ) );
     236          84 :     switch (pNew->Which())
     237             :     {
     238             :         case RES_TXTATR_INETFMT:
     239             :         {
     240          28 :             static_txtattr_cast<SwTxtINetFmt*>(pNew)->InitINetFmt(rNode);
     241          28 :             break;
     242             :         }
     243             :         case RES_TXTATR_CJK_RUBY:
     244             :         {
     245          56 :             static_txtattr_cast<SwTxtRuby*>(pNew)->InitRuby(rNode);
     246          56 :             break;
     247             :         }
     248             :         default:
     249             :             assert(!"MakeTxtAttrNesting: what the hell is that?");
     250           0 :             break;
     251             :     }
     252          84 :     return static_txtattr_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 sal_Int32 nNewStart,
     260             :     const sal_Int32 nOtherStart, const sal_Int32 nOtherEnd, bool bOtherDummy)
     261             : {
     262          60 :     const bool bSplitAtStart(nNewStart < nOtherStart);
     263          60 :     const sal_Int32 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 sal_Int32 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        3486 : void SwpHints::InsertNesting(SwTxtAttrNesting & rNewHint)
     284             : {
     285        3486 :     SwpHintsArray::Insert(& rNewHint);
     286        3486 :     NoteInHistory( & rNewHint, true );
     287        3486 : }
     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        3402 : SwpHints::TryInsertNesting( SwTxtNode & rNode, SwTxtAttrNesting & rNewHint )
     358             : {
     359             : //    INVARIANT:  the nestable hints in the array are properly nested
     360        3402 :     const sal_uInt16 nNewWhich( rNewHint.Which() );
     361        3402 :     const sal_Int32 nNewStart( rNewHint.GetStart() );
     362        3402 :     const sal_Int32 nNewEnd  ( *rNewHint.GetEnd()   );
     363        3402 :     const bool bNewSelfNestable( isSelfNestable(nNewWhich) );
     364             : 
     365             :     assert( (RES_TXTATR_INETFMT   == nNewWhich) ||
     366             :             (RES_TXTATR_CJK_RUBY  == nNewWhich) ||
     367             :             (RES_TXTATR_META      == nNewWhich) ||
     368             :             (RES_TXTATR_METAFIELD == nNewWhich) ||
     369             :             (RES_TXTATR_INPUTFIELD == nNewWhich));
     370             : 
     371        3402 :     NestList_t OverlappingExisting; // existing hints to be split
     372        6804 :     NestList_t OverwrittenExisting; // existing hints to be replaced
     373        6804 :     NestList_t SplitNew;            // new hints to be inserted
     374             : 
     375        3402 :     SplitNew.push_back(& rNewHint);
     376             : 
     377             :     // pass 1: split the inserted hint into fragments if necessary
     378       21990 :     for ( size_t i = 0; i < GetEndCount(); ++i )
     379             :     {
     380       18592 :         SwTxtAttr * const pOther = GetEnd(i);
     381             : 
     382       18592 :         if (pOther->IsNesting())
     383             :         {
     384        4034 :             const sal_uInt16 nOtherWhich( pOther->Which() );
     385        4034 :             const sal_Int32 nOtherStart( pOther->GetStart() );
     386        4034 :             const sal_Int32 nOtherEnd  ( *(pOther)->GetEnd()   );
     387        4034 :             if (isOverlap(nNewStart, nNewEnd, nOtherStart, nOtherEnd ))
     388             :             {
     389          86 :                 switch (splitPolicy(nNewWhich, nOtherWhich))
     390             :                 {
     391             :                     case FAIL:
     392             :                         OSL_TRACE("cannot insert hint: overlap detected");
     393             :                         ::std::for_each(SplitNew.begin(), SplitNew.end(),
     394           4 :                             TxtAttrDeleter(*rNode.GetDoc()));
     395           4 :                         return false;
     396             :                     case SPLIT_NEW:
     397             :                         lcl_DoSplitNew(SplitNew, rNode, nNewStart,
     398          60 :                             nOtherStart, nOtherEnd, pOther->HasDummyChar());
     399          60 :                         break;
     400             :                     case SPLIT_OTHER:
     401             :                         OverlappingExisting.push_back(
     402          22 :                             static_txtattr_cast<SwTxtAttrNesting*>(pOther));
     403          22 :                         break;
     404             :                     default:
     405             :                         assert(!"bad code monkey");
     406           0 :                         break;
     407             :                 }
     408             :             }
     409        3948 :             else if (isNestedAny(nNewStart, nNewEnd, nOtherStart, nOtherEnd))
     410             :             {
     411         416 :                 if (!bNewSelfNestable && (nNewWhich == nOtherWhich))
     412             :                 {
     413             :                 // ruby and hyperlink: if there is nesting, _overwrite_
     414             :                 OverwrittenExisting.push_back(
     415         222 :                     static_txtattr_cast<SwTxtAttrNesting*>(pOther));
     416             :                 }
     417         194 :                 else if ((nNewStart == nOtherStart) && pOther->HasDummyChar())
     418             :                 {
     419          36 :                     if (rNewHint.HasDummyChar())
     420             :                     {
     421             :                         assert(!"ERROR: inserting duplicate CH_TXTATR hint");
     422           0 :                         return false;
     423          36 :                     } else if (nNewEnd < nOtherEnd) {
     424             :                         // other has dummy char, new is inside other, but
     425             :                         // new contains the other's dummy char?
     426             :                         // should be corrected because it may lead to problems
     427             :                         // in SwXMeta::createEnumeration
     428             :                         // SplitNew is sorted, so this is the first split
     429           4 :                         sal_Int32& rStart(SplitNew.front()->GetStart());
     430             :                         assert(rStart == nNewStart);
     431           4 :                         rStart = nNewStart + 1;
     432             :                     }
     433             :                 }
     434             :             }
     435             :         }
     436             :     }
     437             : 
     438             :     assert((isSplittable(nNewWhich) || SplitNew.size() == 1) &&
     439             :             "splitting the unsplittable ???");
     440             : 
     441             :     // pass 2: split existing hints that overlap/nest with new hint
     442             :     // do not iterate over hints array, but over remembered set of overlapping
     443             :     // hints, to keep things simple w.r.t. insertion/removal
     444             :     // N.B: if there is a hint that splits the inserted hint, then
     445             :     // that hint would also have already split any hint in OverlappingExisting
     446             :     // so any hint in OverlappingExisting can be split at most by one hint
     447             :     // in SplitNew, or even not at all (this is not true for existing hints
     448             :     // that go _around_ new hint, which is the raison d'^etre for pass 4)
     449       10260 :     for (NestList_t::iterator itOther = OverlappingExisting.begin();
     450        6840 :             itOther != OverlappingExisting.end(); ++itOther)
     451             :     {
     452          22 :         const sal_Int32 nOtherStart( (*itOther)->GetStart() );
     453          22 :         const sal_Int32 nOtherEnd  ( *(*itOther)->GetEnd()   );
     454             : 
     455         138 :         for (NestList_t::iterator itNew = SplitNew.begin();
     456          92 :                 itNew != SplitNew.end(); ++itNew)
     457             :         {
     458          24 :             const sal_Int32 nSplitNewStart( (*itNew)->GetStart() );
     459          24 :             const sal_Int32 nSplitNewEnd  ( *(*itNew)->GetEnd()   );
     460             :             // 4 cases: within, around, overlap l, overlap r, (OTHER: no action)
     461             :             const bool bRemoveOverlap(
     462          24 :                 !bNewSelfNestable && (nNewWhich == (*itOther)->Which()) );
     463             : 
     464          24 :             switch (ComparePosition(nSplitNewStart, nSplitNewEnd,
     465          24 :                                     nOtherStart,    nOtherEnd))
     466             :             {
     467             :                 case POS_INSIDE:
     468             :                     {
     469             :                         assert(!bRemoveOverlap &&
     470             :                             "this one should be in OverwrittenExisting?");
     471             :                     }
     472           2 :                     break;
     473             :                 case POS_OUTSIDE:
     474             :                 case POS_EQUAL:
     475             :                     {
     476             :                         assert(!"existing hint inside new hint: why?");
     477             :                     }
     478           0 :                     break;
     479             :                 case POS_OVERLAP_BEFORE:
     480             :                     {
     481          10 :                         Delete( *itOther ); // this also does NoteInHistory!
     482          10 :                         (*itOther)->GetStart() = nSplitNewEnd;
     483          10 :                         InsertNesting( **itOther );
     484          10 :                         if (!bRemoveOverlap)
     485             :                         {
     486           6 :                             if ( MAX_HINTS <= Count() )
     487             :                             {
     488             :                                 OSL_FAIL("hints array full :-(");
     489           0 :                                 return false;
     490             :                             }
     491             :                             SwTxtAttrNesting * const pOtherLeft(
     492           6 :                                 MakeTxtAttrNesting( rNode, **itOther,
     493          12 :                                     nOtherStart, nSplitNewEnd ) );
     494           6 :                             InsertNesting( *pOtherLeft );
     495             :                         }
     496             :                     }
     497          10 :                     break;
     498             :                 case POS_OVERLAP_BEHIND:
     499             :                     {
     500          10 :                         Delete( *itOther ); // this also does NoteInHistory!
     501          10 :                         *(*itOther)->GetEnd() = nSplitNewStart;
     502          10 :                         InsertNesting( **itOther );
     503          10 :                         if (!bRemoveOverlap)
     504             :                         {
     505           6 :                             if ( MAX_HINTS <= Count() )
     506             :                             {
     507             :                                 OSL_FAIL("hints array full :-(");
     508           0 :                                 return false;
     509             :                             }
     510             :                             SwTxtAttrNesting * const pOtherRight(
     511           6 :                                 MakeTxtAttrNesting( rNode, **itOther,
     512          12 :                                     nSplitNewStart, nOtherEnd ) );
     513           6 :                             InsertNesting( *pOtherRight );
     514             :                         }
     515             :                     }
     516          10 :                     break;
     517             :                 default:
     518           2 :                     break; // overlap resolved by splitting new: nothing to do
     519             :             }
     520             :         }
     521             :     }
     522             : 
     523        3398 :     if ( MAX_HINTS <= Count() || MAX_HINTS - Count() <= SplitNew.size() )
     524             :     {
     525             :         OSL_FAIL("hints array full :-(");
     526           0 :         return false;
     527             :     }
     528             : 
     529             :     // pass 3: insert new hints
     530       20556 :     for (NestList_t::iterator iter = SplitNew.begin();
     531       13704 :             iter != SplitNew.end(); ++iter)
     532             :     {
     533        3454 :         InsertNesting(**iter);
     534             :     }
     535             : 
     536             :     // pass 4: handle overwritten hints
     537             :     // RES_TXTATR_INETFMT and RES_TXTATR_CJK_RUBY should displace attributes
     538             :     // of the same kind.
     539       10860 :     for (NestList_t::iterator itOther = OverwrittenExisting.begin();
     540        7240 :             itOther != OverwrittenExisting.end(); ++itOther)
     541             :     {
     542         222 :         const sal_Int32 nOtherStart( (*itOther)->GetStart() );
     543         222 :         const sal_Int32 nOtherEnd  ( *(*itOther)->GetEnd()   );
     544             : 
     545             :         // overwritten portion is given by start/end of inserted hint
     546         222 :         if ((nNewStart <= nOtherStart) && (nOtherEnd <= nNewEnd))
     547             :         {
     548         204 :             Delete(*itOther);
     549         204 :             rNode.DestroyAttr( *itOther );
     550             :         }
     551             :         else
     552             :         {
     553             :            assert((nOtherStart < nNewStart) || (nNewEnd < nOtherEnd));
     554             :         // scenario: there is a RUBY, and contained within that a META;
     555             :         // now a RUBY is inserted within the META => the exising RUBY is split:
     556             :         // here it is not possible to simply insert the left/right fragment
     557             :         // of the existing RUBY because they <em>overlap</em> with the META!
     558          18 :             Delete( *itOther ); // this also does NoteInHistory!
     559          18 :             if (nNewEnd < nOtherEnd)
     560             :             {
     561             :                 SwTxtAttrNesting * const pOtherRight(
     562             :                     MakeTxtAttrNesting(
     563          16 :                         rNode, **itOther, nNewEnd, nOtherEnd ) );
     564          16 :                 bool const bSuccess( TryInsertNesting(rNode, *pOtherRight) );
     565             :                 SAL_WARN_IF(!bSuccess, "sw.core", "recursive call 1 failed?");
     566             :             }
     567          18 :             if (nOtherStart < nNewStart)
     568             :             {
     569          16 :                 *(*itOther)->GetEnd() = nNewStart;
     570          16 :                 bool const bSuccess( TryInsertNesting(rNode, **itOther) );
     571             :                 SAL_WARN_IF(!bSuccess, "sw.core", "recursive call 2 failed?");
     572             :             }
     573             :             else
     574             :             {
     575           2 :                 rNode.DestroyAttr(*itOther);
     576             :             }
     577             :         }
     578             :     }
     579             : 
     580        6800 :     return true;
     581             : }
     582             : 
     583             : // This function takes care for the following text attribute:
     584             : // RES_TXTATR_CHARFMT, RES_TXTATR_AUTOFMT
     585             : // These attributes have to be handled in a special way (Portion building).
     586             : 
     587             : // The new attribute will be split by any existing RES_TXTATR_AUTOFMT or
     588             : // RES_TXTATR_CHARFMT. The new attribute itself will
     589             : // split any existing RES_TXTATR_AUTOFMT or RES_TXTATR_CHARFMT.
     590             : 
     591      140626 : void SwpHints::BuildPortions( SwTxtNode& rNode, SwTxtAttr& rNewHint,
     592             :         const SetAttrMode nMode )
     593             : {
     594      140626 :     const sal_uInt16 nWhich = rNewHint.Which();
     595             : 
     596      140626 :     const sal_Int32 nThisStart = rNewHint.GetStart();
     597      140626 :     const sal_Int32 nThisEnd =   *rNewHint.GetEnd();
     598      140626 :     const bool bNoLengthAttribute = nThisStart == nThisEnd;
     599             : 
     600      140626 :     std::vector<SwTxtAttr*> aInsDelHints;
     601      140626 :     std::vector<SwTxtAttr*>::iterator aIter;
     602             : 
     603             :     OSL_ENSURE( RES_TXTATR_CHARFMT == rNewHint.Which() ||
     604             :             RES_TXTATR_AUTOFMT == rNewHint.Which(),
     605             :             "Expecting CHARFMT or AUTOFMT" );
     606             : 
     607             :     // 2. Find the hints which cover the start and end position
     608             :     // of the new hint. These hints have to be split into two portions:
     609             : 
     610      140626 :     if ( !bNoLengthAttribute ) // nothing to do for no length attributes
     611             :     {
     612      443904 :         for ( size_t i = 0; i < Count(); ++i )
     613             :         {
     614      354944 :             SwTxtAttr* pOther = GetTextHint(i);
     615             : 
     616      673892 :             if ( RES_TXTATR_CHARFMT != pOther->Which() &&
     617      318948 :                  RES_TXTATR_AUTOFMT != pOther->Which() )
     618       41914 :                 continue;
     619             : 
     620      313030 :             sal_Int32 nOtherStart = pOther->GetStart();
     621      313030 :             const sal_Int32 nOtherEnd = *pOther->GetEnd();
     622             : 
     623             :             // Check if start of new attribute overlaps with pOther:
     624             :             // Split pOther if necessary:
     625      313030 :             if ( nOtherStart < nThisStart && nThisStart < nOtherEnd )
     626             :             {
     627         626 :                 SwTxtAttr* pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
     628        1252 :                         pOther->GetAttr(), nOtherStart, nThisStart );
     629         626 :                 if ( RES_TXTATR_CHARFMT == pOther->Which() )
     630             :                 {
     631             :                     static_txtattr_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber(
     632         152 :                         static_txtattr_cast<SwTxtCharFmt*>(pOther)->GetSortNumber() );
     633             :                 }
     634         626 :                 aInsDelHints.push_back( pNewAttr );
     635             : 
     636         626 :                 NoteInHistory( pOther );
     637         626 :                 pOther->GetStart() = nThisStart;
     638         626 :                 NoteInHistory( pOther, true );
     639             : 
     640         626 :                 nOtherStart = nThisStart;
     641             :             }
     642             : 
     643             :             // Check if end of new attribute overlaps with pOther:
     644             :             // Split pOther if necessary:
     645      313030 :             if ( nOtherStart < nThisEnd && nThisEnd < nOtherEnd )
     646             :             {
     647        1730 :                 SwTxtAttr* pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
     648        3460 :                         pOther->GetAttr(), nOtherStart, nThisEnd );
     649        1730 :                 if ( RES_TXTATR_CHARFMT == pOther->Which() )
     650             :                 {
     651             :                     static_txtattr_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber(
     652           0 :                         static_txtattr_cast<SwTxtCharFmt*>(pOther)->GetSortNumber());
     653             :                 }
     654        1730 :                 aInsDelHints.push_back( pNewAttr );
     655             : 
     656        1730 :                 NoteInHistory( pOther );
     657        1730 :                 pOther->GetStart() = nThisEnd;
     658        1730 :                 NoteInHistory( pOther, true );
     659             :             }
     660             :         }
     661             : 
     662             :         // Insert the newly created attributes:
     663       91316 :         for ( aIter = aInsDelHints.begin(); aIter != aInsDelHints.end(); ++aIter )
     664             :         {
     665        2356 :             SwpHintsArray::Insert( *aIter );
     666        2356 :             NoteInHistory( *aIter, true );
     667             :         }
     668             :     }
     669             : 
     670             : #ifdef DBG_UTIL
     671             :     if( !rNode.GetDoc()->IsInReading() )
     672             :         CHECK_NOTMERGED; // ignore flags not set properly yet, don't check them
     673             : #endif
     674             : 
     675             :     // 4. Split rNewHint into 1 ... n new hints:
     676             : 
     677      281252 :     std::set<sal_Int32> aBounds;
     678      140626 :     aBounds.insert( nThisStart );
     679      140626 :     aBounds.insert( nThisEnd );
     680             : 
     681      140626 :     if ( !bNoLengthAttribute ) // nothing to do for no length attributes
     682             :     {
     683      446260 :         for ( size_t i = 0; i < Count(); ++i )
     684             :         {
     685      357300 :             const SwTxtAttr* pOther = GetTextHint(i);
     686             : 
     687      678452 :             if ( RES_TXTATR_CHARFMT != pOther->Which() &&
     688      321152 :                  RES_TXTATR_AUTOFMT != pOther->Which() )
     689       41914 :                 continue;
     690             : 
     691      315386 :             const sal_Int32 nOtherStart = pOther->GetStart();
     692      315386 :             const sal_Int32 nOtherEnd = *pOther->End();
     693             : 
     694      315386 :             aBounds.insert( nOtherStart );
     695      315386 :             aBounds.insert( nOtherEnd );
     696             :         }
     697             :     }
     698             : 
     699      140626 :     std::set<sal_Int32>::iterator aStartIter = aBounds.lower_bound( nThisStart );
     700      140626 :     std::set<sal_Int32>::iterator aEndIter = aBounds.upper_bound( nThisEnd );
     701      140626 :     sal_Int32 nPorStart = *aStartIter;
     702      140626 :     ++aStartIter;
     703      140626 :     bool bDestroyHint = true;
     704             : 
     705             :     // Insert the 1...n new parts of the new attribute:
     706             : 
     707      372246 :     while ( aStartIter != aEndIter || bNoLengthAttribute )
     708             :     {
     709             :         OSL_ENSURE( bNoLengthAttribute || nPorStart < *aStartIter, "AUTOSTYLES: BuildPortion trouble" );
     710             : 
     711      142660 :         const sal_Int32 nPorEnd = bNoLengthAttribute ? nPorStart : *aStartIter;
     712      142660 :         aInsDelHints.clear();
     713             : 
     714             :         // Get all hints that are in [nPorStart, nPorEnd[:
     715      640960 :         for ( size_t i = 0; i < Count(); ++i )
     716             :         {
     717      502862 :             SwTxtAttr *pOther = GetTextHint(i);
     718             : 
     719      958304 :             if ( RES_TXTATR_CHARFMT != pOther->Which() &&
     720      455442 :                  RES_TXTATR_AUTOFMT != pOther->Which() )
     721       48784 :                 continue;
     722             : 
     723      454078 :             const sal_Int32 nOtherStart = pOther->GetStart();
     724             : 
     725      454078 :             if ( nOtherStart > nPorStart )
     726        4562 :                 break;
     727             : 
     728      449516 :             if ( pOther->GetEnd() && *pOther->GetEnd() == nPorEnd && nOtherStart == nPorStart )
     729             :             {
     730             :                 OSL_ENSURE( *pOther->GetEnd() == nPorEnd, "AUTOSTYLES: BuildPortion trouble" );
     731       50700 :                 aInsDelHints.push_back( pOther );
     732             :             }
     733             :         }
     734             : 
     735      142660 :         SwTxtAttr* pNewAttr = 0;
     736      142660 :         if ( RES_TXTATR_CHARFMT == nWhich )
     737             :         {
     738             :             // pNewHint can be inserted after calculating the sort value.
     739             :             // This should ensure, that pNewHint comes behind the already present
     740             :             // character style
     741       12210 :             sal_uInt16 nCharStyleCount = 0;
     742       12210 :             aIter = aInsDelHints.begin();
     743       26302 :             while ( aIter != aInsDelHints.end() )
     744             :             {
     745        1882 :                 if ( RES_TXTATR_CHARFMT == (*aIter)->Which() )
     746             :                 {
     747             :                     // #i74589#
     748        1356 :                     const SwFmtCharFmt& rOtherCharFmt = (*aIter)->GetCharFmt();
     749        1356 :                     const SwFmtCharFmt& rThisCharFmt = rNewHint.GetCharFmt();
     750        1356 :                     const bool bSameCharFmt = rOtherCharFmt.GetCharFmt() == rThisCharFmt.GetCharFmt();
     751             : 
     752             :                     // #i90311#
     753             :                     // Do not remove existing character format hint during XML import
     754        4068 :                     if ( !rNode.GetDoc()->IsInXMLImport() &&
     755        1356 :                          ( !( nsSetAttrMode::SETATTR_DONTREPLACE & nMode ) ||
     756           0 :                            bNoLengthAttribute ||
     757             :                            bSameCharFmt ) )
     758             :                     {
     759             :                         // Remove old hint
     760        1356 :                         Delete( *aIter );
     761        1356 :                         rNode.DestroyAttr( *aIter );
     762             :                     }
     763             :                     else
     764           0 :                         ++nCharStyleCount;
     765             :                 }
     766             :                 else
     767             :                 {
     768             :                     // remove all attributes from auto styles, which are explicitly set in
     769             :                     // the new character format:
     770             :                     OSL_ENSURE( RES_TXTATR_AUTOFMT == (*aIter)->Which(), "AUTOSTYLES - Misc trouble" );
     771         526 :                     SwTxtAttr* pOther = *aIter;
     772         526 :                     boost::shared_ptr<SfxItemSet> pOldStyle = static_cast<const SwFmtAutoFmt&>(pOther->GetAttr()).GetStyleHandle();
     773             : 
     774             :                     // For each attribute in the automatic style check if it
     775             :                     // is also set the new character style:
     776         526 :                     SfxItemSet aNewSet( *pOldStyle->GetPool(),
     777        1052 :                         aCharAutoFmtSetRange);
     778        1052 :                     SfxItemIter aItemIter( *pOldStyle );
     779         526 :                     const SfxPoolItem* pItem = aItemIter.GetCurItem();
     780             :                     while( true )
     781             :                     {
     782        1776 :                         if ( !CharFmt::IsItemIncluded( pItem->Which(), &rNewHint ) )
     783             :                         {
     784         750 :                             aNewSet.Put( *pItem );
     785             :                         }
     786             : 
     787        1776 :                         if( aItemIter.IsAtEnd() )
     788         526 :                             break;
     789             : 
     790        1250 :                         pItem = aItemIter.NextItem();
     791             :                     }
     792             : 
     793             :                     // Remove old hint
     794         526 :                     Delete( pOther );
     795         526 :                     rNode.DestroyAttr( pOther );
     796             : 
     797             :                     // Create new AutoStyle
     798         526 :                     if ( aNewSet.Count() )
     799             :                     {
     800         192 :                         pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
     801         192 :                                 aNewSet, nPorStart, nPorEnd );
     802         192 :                         SwpHintsArray::Insert( pNewAttr );
     803         192 :                         NoteInHistory( pNewAttr, true );
     804         526 :                     }
     805             :                 }
     806        1882 :                 ++aIter;
     807             :             }
     808             : 
     809             :             // If there is no current hint and start and end of rNewHint
     810             :             // is ok, we do not need to create a new txtattr.
     811       24420 :             if ( nPorStart == nThisStart &&
     812       24420 :                  nPorEnd == nThisEnd &&
     813             :                  !nCharStyleCount )
     814             :             {
     815       12210 :                 pNewAttr = &rNewHint;
     816       12210 :                 bDestroyHint = false;
     817             :             }
     818             :             else
     819             :             {
     820           0 :                 pNewAttr = MakeTxtAttr( *rNode.GetDoc(), rNewHint.GetAttr(),
     821           0 :                         nPorStart, nPorEnd );
     822           0 :                 static_txtattr_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber(nCharStyleCount);
     823             :             }
     824             :         }
     825             :         else
     826             :         {
     827             :             // Find the current autostyle. Mix attributes if necessary.
     828      130450 :             SwTxtAttr* pCurrentAutoStyle = 0;
     829      130450 :             SwTxtAttr* pCurrentCharFmt = 0;
     830      130450 :             aIter = aInsDelHints.begin();
     831      309718 :             while ( aIter != aInsDelHints.end() )
     832             :             {
     833       48818 :                 if ( RES_TXTATR_AUTOFMT == (*aIter)->Which() )
     834       46384 :                     pCurrentAutoStyle = *aIter;
     835        2434 :                 else if ( RES_TXTATR_CHARFMT == (*aIter)->Which() )
     836        2434 :                     pCurrentCharFmt = *aIter;
     837       48818 :                 ++aIter;
     838             :             }
     839             : 
     840      130450 :             boost::shared_ptr<SfxItemSet> pNewStyle = static_cast<const SwFmtAutoFmt&>(rNewHint.GetAttr()).GetStyleHandle();
     841      130450 :             if ( pCurrentAutoStyle )
     842             :             {
     843       46384 :                 boost::shared_ptr<SfxItemSet> pCurrentStyle = static_cast<const SwFmtAutoFmt&>(pCurrentAutoStyle->GetAttr()).GetStyleHandle();
     844             : 
     845             :                 // Merge attributes
     846       92768 :                 SfxItemSet aNewSet( *pCurrentStyle );
     847       46384 :                 aNewSet.Put( *pNewStyle );
     848             : 
     849             :                 // #i75750# Remove attributes already set at whole paragraph
     850             :                 // #i81764# This should not be applied for no length attributes!!! <--
     851       46384 :                 if ( !bNoLengthAttribute && rNode.HasSwAttrSet() && aNewSet.Count() )
     852             :                 {
     853       16526 :                     SfxItemIter aIter2( aNewSet );
     854       16526 :                     const SfxPoolItem* pItem = aIter2.GetCurItem();
     855       16526 :                     const SfxItemSet& rWholeParaAttrSet = rNode.GetSwAttrSet();
     856             : 
     857       82962 :                     do
     858             :                     {
     859       82962 :                         const SfxPoolItem* pTmpItem = 0;
     860       83082 :                         if ( SfxItemState::SET == rWholeParaAttrSet.GetItemState( pItem->Which(), false, &pTmpItem ) &&
     861         120 :                              pTmpItem == pItem )
     862             :                         {
     863             :                             // Do not clear item if the attribute is set in a character format:
     864           0 :                             if ( !pCurrentCharFmt || 0 == CharFmt::GetItem( *pCurrentCharFmt, pItem->Which() ) )
     865           0 :                                 aNewSet.ClearItem( pItem->Which() );
     866             :                         }
     867             :                     }
     868       99488 :                     while (!aIter2.IsAtEnd() && 0 != (pItem = aIter2.NextItem()));
     869             :                 }
     870             : 
     871             :                 // Remove old hint
     872       46384 :                 Delete( pCurrentAutoStyle );
     873       46384 :                 rNode.DestroyAttr( pCurrentAutoStyle );
     874             : 
     875             :                 // Create new AutoStyle
     876       46384 :                 if ( aNewSet.Count() )
     877       46384 :                     pNewAttr = MakeTxtAttr( *rNode.GetDoc(), aNewSet,
     878       92768 :                             nPorStart, nPorEnd );
     879             :             }
     880             :             else
     881             :             {
     882             :                 // Remove any attributes which are already set at the whole paragraph:
     883       84066 :                 bool bOptimizeAllowed = true;
     884             : 
     885       84066 :                 SfxItemSet* pNewSet = 0;
     886             :                 // #i75750# Remove attributes already set at whole paragraph
     887             :                 // #i81764# This should not be applied for no length attributes!!! <--
     888       84066 :                 if ( !bNoLengthAttribute && rNode.HasSwAttrSet() && pNewStyle->Count() )
     889             :                 {
     890        9786 :                     SfxItemIter aIter2( *pNewStyle );
     891        9786 :                     const SfxPoolItem* pItem = aIter2.GetCurItem();
     892        9786 :                     const SfxItemSet& rWholeParaAttrSet = rNode.GetSwAttrSet();
     893             : 
     894       43302 :                     do
     895             :                     {
     896       43302 :                         const SfxPoolItem* pTmpItem = 0;
     897       43330 :                         if ( SfxItemState::SET == rWholeParaAttrSet.GetItemState( pItem->Which(), false, &pTmpItem ) &&
     898          28 :                              pTmpItem == pItem )
     899             :                         {
     900             :                             // Do not clear item if the attribute is set in a character format:
     901          28 :                             if ( !pCurrentCharFmt || 0 == CharFmt::GetItem( *pCurrentCharFmt, pItem->Which() ) )
     902             :                             {
     903          28 :                                 if ( !pNewSet )
     904          16 :                                     pNewSet = pNewStyle->Clone( true );
     905          28 :                                 pNewSet->ClearItem( pItem->Which() );
     906             :                             }
     907             :                         }
     908             :                     }
     909       43302 :                     while (!aIter2.IsAtEnd() && 0 != (pItem = aIter2.NextItem()));
     910             : 
     911        9786 :                     if ( pNewSet )
     912             :                     {
     913          16 :                         bOptimizeAllowed = false;
     914          16 :                         if ( pNewSet->Count() )
     915           0 :                             pNewStyle = rNode.getIDocumentStyleAccess().getAutomaticStyle( *pNewSet, IStyleAccess::AUTO_STYLE_CHAR );
     916             :                         else
     917          16 :                             pNewStyle.reset();
     918             : 
     919          16 :                         delete pNewSet;
     920        9786 :                     }
     921             :                 }
     922             : 
     923             :                 // Create new AutoStyle
     924             :                 // If there is no current hint and start and end of rNewHint
     925             :                 // is ok, we do not need to create a new txtattr.
     926      168116 :                 if ( bOptimizeAllowed &&
     927      168034 :                      nPorStart == nThisStart &&
     928       83984 :                      nPorEnd == nThisEnd )
     929             :                 {
     930       83974 :                     pNewAttr = &rNewHint;
     931       83974 :                     bDestroyHint = false;
     932             :                 }
     933          92 :                 else if ( pNewStyle.get() )
     934             :                 {
     935          76 :                     pNewAttr = MakeTxtAttr( *rNode.GetDoc(), *pNewStyle,
     936          76 :                             nPorStart, nPorEnd );
     937             :                 }
     938      130450 :             }
     939             :         }
     940             : 
     941      142660 :         if ( pNewAttr )
     942             :         {
     943      142644 :             SwpHintsArray::Insert( pNewAttr );
     944             : //            if ( bDestroyHint )
     945      142644 :                 NoteInHistory( pNewAttr, true );
     946             :         }
     947             : 
     948      142660 :         if ( !bNoLengthAttribute )
     949             :         {
     950       90994 :             nPorStart = *aStartIter;
     951       90994 :             ++aStartIter;
     952             :         }
     953             :         else
     954       51666 :             break;
     955             :     }
     956             : 
     957      140626 :     if ( bDestroyHint )
     958      185068 :         rNode.DestroyAttr( &rNewHint );
     959      140626 : }
     960             : 
     961        9850 : SwTxtAttr* MakeRedlineTxtAttr( SwDoc & rDoc, SfxPoolItem & rAttr )
     962             : {
     963             :     // this is intended _only_ for special-purpose redline attributes!
     964        9850 :     switch (rAttr.Which())
     965             :     {
     966             :         case RES_CHRATR_COLOR:
     967             :         case RES_CHRATR_WEIGHT:
     968             :         case RES_CHRATR_CJK_WEIGHT:
     969             :         case RES_CHRATR_CTL_WEIGHT:
     970             :         case RES_CHRATR_POSTURE:
     971             :         case RES_CHRATR_CJK_POSTURE:
     972             :         case RES_CHRATR_CTL_POSTURE:
     973             :         case RES_CHRATR_UNDERLINE:
     974             :         case RES_CHRATR_CROSSEDOUT:
     975             :         case RES_CHRATR_CASEMAP:
     976             :         case RES_CHRATR_BACKGROUND:
     977        9850 :             break;
     978             :         default:
     979             :             OSL_FAIL("unsupported redline attribute");
     980           0 :             break;
     981             :     }
     982             : 
     983             :     // Put new attribute into pool
     984             :     // FIXME: this const_cast is evil!
     985             :     SfxPoolItem& rNew =
     986        9850 :         const_cast<SfxPoolItem&>( rDoc.GetAttrPool().Put( rAttr ) );
     987        9850 :     return new SwTxtAttrEnd( rNew, 0, 0 );
     988             : }
     989             : 
     990             : // create new text attribute
     991      206628 : SwTxtAttr* MakeTxtAttr(
     992             :     SwDoc & rDoc,
     993             :     SfxPoolItem& rAttr,
     994             :     sal_Int32 const nStt,
     995             :     sal_Int32 const nEnd,
     996             :     CopyOrNew_t const bIsCopy,
     997             :     SwTxtNode *const pTxtNode )
     998             : {
     999      206628 :     if ( isCHRATR(rAttr.Which()) )
    1000             :     {
    1001             :         // Somebody wants to build a SwTxtAttr for a character attribute.
    1002             :         // Sorry, this is not allowed any longer.
    1003             :         // You'll get a brand new autostyle attribute:
    1004           0 :         SfxItemSet aItemSet( rDoc.GetAttrPool(),
    1005           0 :                 RES_CHRATR_BEGIN, RES_CHRATR_END );
    1006           0 :         aItemSet.Put( rAttr );
    1007           0 :         return MakeTxtAttr( rDoc, aItemSet, nStt, nEnd );
    1008             :     }
    1009      800212 :     else if ( RES_TXTATR_AUTOFMT == rAttr.Which() &&
    1010             :               static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle()->
    1011      747612 :                 GetPool() != &rDoc.GetAttrPool() )
    1012             :     {
    1013             :         // If the attribute is an auto-style which refers to a pool that is
    1014             :         // different from rDoc's pool, we have to correct this:
    1015          12 :         const StylePool::SfxItemSet_Pointer_t pAutoStyle = static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle();
    1016             :         boost::scoped_ptr<const SfxItemSet> pNewSet(
    1017          24 :                 pAutoStyle->SfxItemSet::Clone( true, &rDoc.GetAttrPool() ));
    1018          12 :         SwTxtAttr* pNew = MakeTxtAttr( rDoc, *pNewSet, nStt, nEnd );
    1019          24 :         return pNew;
    1020             :     }
    1021             : 
    1022             :     // Put new attribute into pool
    1023             :     // FIXME: this const_cast is evil!
    1024             :     SfxPoolItem& rNew =
    1025      206616 :         const_cast<SfxPoolItem&>( rDoc.GetAttrPool().Put( rAttr ) );
    1026             : 
    1027      206616 :     SwTxtAttr* pNew = 0;
    1028      206616 :     switch( rNew.Which() )
    1029             :     {
    1030             :     case RES_TXTATR_CHARFMT:
    1031             :         {
    1032       12362 :             SwFmtCharFmt &rFmtCharFmt = (SwFmtCharFmt&) rNew;
    1033       12362 :             if( !rFmtCharFmt.GetCharFmt() )
    1034             :             {
    1035           0 :                 rFmtCharFmt.SetCharFmt( rDoc.GetDfltCharFmt() );
    1036             :             }
    1037             : 
    1038       12362 :             pNew = new SwTxtCharFmt( rFmtCharFmt, nStt, nEnd );
    1039             :         }
    1040       12362 :         break;
    1041             :     case RES_TXTATR_INETFMT:
    1042        2864 :         pNew = new SwTxtINetFmt( (SwFmtINetFmt&)rNew, nStt, nEnd );
    1043        2864 :         break;
    1044             : 
    1045             :     case RES_TXTATR_FIELD:
    1046        5476 :         pNew = new SwTxtFld( static_cast<SwFmtFld &>(rNew), nStt,
    1047        8214 :                     rDoc.IsClipBoard() );
    1048        2738 :         break;
    1049             : 
    1050             :     case RES_TXTATR_ANNOTATION:
    1051             :         {
    1052         192 :             pNew = new SwTxtAnnotationFld( static_cast<SwFmtFld &>(rNew), nStt, rDoc.IsClipBoard() );
    1053         192 :             if (bIsCopy == COPY)
    1054             :             {
    1055             :                 // On copy of the annotation field do not keep the annotated text range by removing
    1056             :                 // the relation to its annotation mark (relation established via annotation field's name).
    1057             :                 // If the annotation mark is also copied, the relation and thus the annotated text range will be reestablished,
    1058             :                 // when the annotation mark is created and inserted into the document.
    1059          10 :                 const_cast<SwPostItField&>(dynamic_cast<const SwPostItField&>(*(pNew->GetFmtFld().GetField()))).SetName(OUString());
    1060             :             }
    1061             :         }
    1062         192 :         break;
    1063             : 
    1064             :     case RES_TXTATR_INPUTFIELD:
    1065          56 :         pNew = new SwTxtInputFld( static_cast<SwFmtFld &>(rNew), nStt, nEnd,
    1066          84 :                     rDoc.IsClipBoard() );
    1067          28 :         break;
    1068             : 
    1069             :     case RES_TXTATR_FLYCNT:
    1070             :         {
    1071             :             // erst hier wird das Frame-Format kopiert (mit Inhalt) !!
    1072        6870 :             pNew = new SwTxtFlyCnt( (SwFmtFlyCnt&)rNew, nStt );
    1073             :             // Kopie von einem Text-Attribut
    1074        6870 :             if ( static_cast<const SwFmtFlyCnt &>(rAttr).GetTxtFlyCnt() )
    1075             :             {
    1076             :                 // then the format must be copied
    1077         272 :                 static_cast<SwTxtFlyCnt *>(pNew)->CopyFlyFmt( &rDoc );
    1078             :             }
    1079             :         }
    1080        6870 :         break;
    1081             :     case RES_TXTATR_FTN:
    1082         268 :         pNew = new SwTxtFtn( (SwFmtFtn&)rNew, nStt );
    1083             :         // ggfs. SeqNo kopieren
    1084         268 :         if( ((SwFmtFtn&)rAttr).GetTxtFtn() )
    1085           0 :             ((SwTxtFtn*)pNew)->SetSeqNo( ((SwFmtFtn&)rAttr).GetTxtFtn()->GetSeqRefNo() );
    1086         268 :         break;
    1087             :     case RES_TXTATR_REFMARK:
    1088         164 :         pNew = nStt == nEnd
    1089          54 :                 ? new SwTxtRefMark( (SwFmtRefMark&)rNew, nStt )
    1090         110 :                 : new SwTxtRefMark( (SwFmtRefMark&)rNew, nStt, &nEnd );
    1091          82 :         break;
    1092             :     case RES_TXTATR_TOXMARK:
    1093         342 :         pNew = new SwTxtTOXMark( (SwTOXMark&)rNew, nStt, &nEnd );
    1094         342 :         break;
    1095             :     case RES_TXTATR_CJK_RUBY:
    1096         360 :         pNew = new SwTxtRuby( (SwFmtRuby&)rNew, nStt, nEnd );
    1097         360 :         break;
    1098             :     case RES_TXTATR_META:
    1099             :     case RES_TXTATR_METAFIELD:
    1100         388 :         pNew = SwTxtMeta::CreateTxtMeta( rDoc.GetMetaFieldManager(), pTxtNode,
    1101         582 :                 static_cast<SwFmtMeta&>(rNew), nStt, nEnd, bIsCopy == COPY );
    1102         194 :         break;
    1103             :     default:
    1104             :         OSL_ENSURE(RES_TXTATR_AUTOFMT == rNew.Which(), "unknown attribute");
    1105      180316 :         pNew = new SwTxtAttrEnd( rNew, nStt, nEnd );
    1106      180316 :         break;
    1107             :     }
    1108             : 
    1109      206616 :     return pNew;
    1110             : }
    1111             : 
    1112      171450 : SwTxtAttr* MakeTxtAttr( SwDoc & rDoc, const SfxItemSet& rSet,
    1113             :                         sal_Int32 nStt, sal_Int32 nEnd )
    1114             : {
    1115      171450 :     IStyleAccess& rStyleAccess = rDoc.GetIStyleAccess();
    1116      171450 :     const StylePool::SfxItemSet_Pointer_t pAutoStyle = rStyleAccess.getAutomaticStyle( rSet, IStyleAccess::AUTO_STYLE_CHAR );
    1117      342900 :     SwFmtAutoFmt aNewAutoFmt;
    1118      171450 :     aNewAutoFmt.SetStyleHandle( pAutoStyle );
    1119      171450 :     SwTxtAttr* pNew = MakeTxtAttr( rDoc, aNewAutoFmt, nStt, nEnd );
    1120      342900 :     return pNew;
    1121             : }
    1122             : 
    1123             : // loesche das Text-Attribut (muss beim Pool abgemeldet werden!)
    1124      206582 : void SwTxtNode::DestroyAttr( SwTxtAttr* pAttr )
    1125             : {
    1126      206582 :     if( pAttr )
    1127             :     {
    1128             :         // einige Sachen muessen vorm Loeschen der "Format-Attribute" erfolgen
    1129      206582 :         SwDoc* pDoc = GetDoc();
    1130      206582 :         switch( pAttr->Which() )
    1131             :         {
    1132             :         case RES_TXTATR_FLYCNT:
    1133             :             {
    1134             :                 // siehe auch die Anmerkung "Loeschen von Formaten
    1135             :                 // zeichengebundener Frames" in fesh.cxx, SwFEShell::DelFmt()
    1136        6868 :                 SwFrmFmt* pFmt = pAttr->GetFlyCnt().GetFrmFmt();
    1137        6868 :                 if( pFmt )      // vom Undo auf 0 gesetzt ??
    1138        2794 :                     pDoc->getIDocumentLayoutAccess().DelLayoutFmt( pFmt );
    1139             :             }
    1140        6868 :             break;
    1141             : 
    1142             :         case RES_CHRATR_HIDDEN:
    1143           0 :             SetCalcHiddenCharFlags();
    1144           0 :             break;
    1145             : 
    1146             :         case RES_TXTATR_FTN:
    1147         268 :             ((SwTxtFtn*)pAttr)->SetStartNode( 0 );
    1148         268 :             static_cast<SwFmtFtn&>(pAttr->GetAttr()).InvalidateFootnote();
    1149         268 :             break;
    1150             : 
    1151             :         case RES_TXTATR_FIELD:
    1152             :         case RES_TXTATR_ANNOTATION:
    1153             :         case RES_TXTATR_INPUTFIELD:
    1154        2940 :             if( !pDoc->IsInDtor() )
    1155             :             {
    1156         942 :                 SwTxtFld *const pTxtFld(static_txtattr_cast<SwTxtFld*>(pAttr));
    1157             :                 // Wenn wir ein HiddenParaField sind, dann muessen wir
    1158             :                 // ggf. fuer eine Neuberechnung des Visible-Flags sorgen.
    1159         942 :                 const SwField* pFld = pAttr->GetFmtFld().GetField();
    1160             : 
    1161             :                 //JP 06-08-95: DDE-Felder bilden eine Ausnahme
    1162             :                 OSL_ENSURE( RES_DDEFLD == pFld->GetTyp()->Which() ||
    1163             :                         this == pTxtFld->GetpTxtNode(),
    1164             :                         "Wo steht denn dieses Feld?" );
    1165             : 
    1166             :                 // bestimmte Felder mussen am Doc das Calculations-Flag updaten
    1167         942 :                 switch( pFld->GetTyp()->Which() )
    1168             :                 {
    1169             :                 case RES_HIDDENPARAFLD:
    1170           0 :                     SetCalcHiddenParaField();
    1171             :                     // no break
    1172             :                 case RES_DBSETNUMBERFLD:
    1173             :                 case RES_GETEXPFLD:
    1174             :                 case RES_DBFLD:
    1175             :                 case RES_SETEXPFLD:
    1176             :                 case RES_HIDDENTXTFLD:
    1177             :                 case RES_DBNUMSETFLD:
    1178             :                 case RES_DBNEXTSETFLD:
    1179          18 :                     if( !pDoc->getIDocumentFieldsAccess().IsNewFldLst() && GetNodes().IsDocNodes() )
    1180          16 :                         pDoc->getIDocumentFieldsAccess().InsDelFldInFldLst(false, *pTxtFld);
    1181          18 :                     break;
    1182             :                 case RES_DDEFLD:
    1183           0 :                     if (GetNodes().IsDocNodes() && pTxtFld->GetpTxtNode())
    1184           0 :                         ((SwDDEFieldType*)pFld->GetTyp())->DecRefCnt();
    1185           0 :                     break;
    1186             :                 case RES_POSTITFLD:
    1187             :                     {
    1188          34 :                         const_cast<SwFmtFld&>(pAttr->GetFmtFld()).Broadcast(
    1189          68 :                             SwFmtFldHint(&pTxtFld->GetFmtFld(), SwFmtFldHintWhich::REMOVED));
    1190          34 :                         break;
    1191             :                     }
    1192             :                 }
    1193             :             }
    1194        2940 :             static_cast<SwFmtFld&>(pAttr->GetAttr()).InvalidateField();
    1195        2940 :             break;
    1196             : 
    1197             :         case RES_TXTATR_TOXMARK:
    1198         342 :             static_cast<SwTOXMark&>(pAttr->GetAttr()).InvalidateTOXMark();
    1199         342 :             break;
    1200             : 
    1201             :         case RES_TXTATR_REFMARK:
    1202          82 :             static_cast<SwFmtRefMark&>(pAttr->GetAttr()).InvalidateRefMark();
    1203          82 :             break;
    1204             : 
    1205             :         case RES_TXTATR_META:
    1206             :         case RES_TXTATR_METAFIELD:
    1207         190 :             static_txtattr_cast<SwTxtMeta*>(pAttr)->ChgTxtNode(0);
    1208         190 :             break;
    1209             : 
    1210             :         default:
    1211      195892 :             break;
    1212             :         }
    1213             : 
    1214      206582 :         SwTxtAttr::Destroy( pAttr, pDoc->GetAttrPool() );
    1215             :     }
    1216      206582 : }
    1217             : 
    1218       11074 : SwTxtAttr* SwTxtNode::InsertItem(
    1219             :     SfxPoolItem& rAttr,
    1220             :     const sal_Int32 nStart,
    1221             :     const sal_Int32 nEnd,
    1222             :     const SetAttrMode nMode )
    1223             : {
    1224             :    // character attributes will be inserted as automatic styles:
    1225             :     OSL_ENSURE( !isCHRATR(rAttr.Which()), "AUTOSTYLES - "
    1226             :         "SwTxtNode::InsertItem should not be called with character attributes");
    1227             : 
    1228             :     SwTxtAttr *const pNew =
    1229             :         MakeTxtAttr(
    1230       11074 :             *GetDoc(),
    1231             :             rAttr,
    1232             :             nStart,
    1233             :             nEnd,
    1234       11074 :             (nMode & nsSetAttrMode::SETATTR_IS_COPY) ? COPY : NEW,
    1235       22148 :             this );
    1236             : 
    1237       11074 :     if ( pNew )
    1238             :     {
    1239       11074 :         const bool bSuccess( InsertHint( pNew, nMode ) );
    1240             :         // N.B.: also check that the hint is actually in the hints array,
    1241             :         // because hints of certain types may be merged after successful
    1242             :         // insertion, and thus destroyed!
    1243       11074 :         if (!bSuccess || !m_pSwpHints->Contains( pNew ))
    1244             :         {
    1245           0 :             return 0;
    1246             :         }
    1247             :     }
    1248             : 
    1249       11074 :     return pNew;
    1250             : }
    1251             : 
    1252             : // take ownership of pAttr; if insertion fails, delete pAttr
    1253      157690 : bool SwTxtNode::InsertHint( SwTxtAttr * const pAttr, const SetAttrMode nMode )
    1254             : {
    1255      157690 :     bool bHiddenPara = false;
    1256             : 
    1257             :     OSL_ENSURE( pAttr && pAttr->GetStart() <= Len(), "StartIdx out of bounds!" );
    1258             :     OSL_ENSURE( !pAttr->GetEnd() || (*pAttr->GetEnd() <= Len()),
    1259             :             "EndIdx out of bounds!" );
    1260             : 
    1261             :     // translate from SetAttrMode to InsertMode (for hints with CH_TXTATR)
    1262             :     const enum IDocumentContentOperations::InsertFlags nInsertFlags =
    1263      157690 :         (nMode & nsSetAttrMode::SETATTR_FORCEHINTEXPAND)
    1264             :         ? static_cast<IDocumentContentOperations::InsertFlags>(
    1265             :                 IDocumentContentOperations::INS_FORCEHINTEXPAND |
    1266             :                 IDocumentContentOperations::INS_EMPTYEXPAND)
    1267      157690 :         : IDocumentContentOperations::INS_EMPTYEXPAND;
    1268             : 
    1269             :     // need this after TryInsertHint, when pAttr may be deleted
    1270      157690 :     const sal_Int32 nStart( pAttr->GetStart() );
    1271      157690 :     const bool bDummyChar( pAttr->HasDummyChar() );
    1272      157690 :     if (bDummyChar)
    1273             :     {
    1274       10648 :         sal_uInt16 nInsMode = nMode;
    1275       10648 :         switch( pAttr->Which() )
    1276             :         {
    1277             :         case RES_TXTATR_FLYCNT:
    1278             :             {
    1279        6880 :                 SwTxtFlyCnt *pFly = (SwTxtFlyCnt *)pAttr;
    1280        6880 :                 SwFrmFmt* pFmt = pAttr->GetFlyCnt().GetFrmFmt();
    1281        6880 :                 if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
    1282             :                 {
    1283             :                     // Wir muessen zuerst einfuegen, da in SetAnchor()
    1284             :                     // dem FlyFrm GetStart() uebermittelt wird.
    1285             :                     //JP 11.05.98: falls das Anker-Attribut schon richtig
    1286             :                     // gesetzt ist, dann korrigiere dieses nach dem Einfuegen
    1287             :                     // des Zeichens. Sonst muesste das immer  ausserhalb
    1288             :                     // erfolgen (Fehleranfaellig !)
    1289        6598 :                     const SwFmtAnchor* pAnchor = 0;
    1290             :                     pFmt->GetItemState( RES_ANCHOR, false,
    1291        6598 :                         (const SfxPoolItem**)&pAnchor );
    1292             : 
    1293        6598 :                     SwIndex aIdx( this, pAttr->GetStart() );
    1294       13196 :                     const OUString c(GetCharOfTxtAttr(*pAttr));
    1295       13196 :                     OUString const ins( InsertText(c, aIdx, nInsertFlags) );
    1296        6598 :                     if (ins.isEmpty())
    1297             :                     {
    1298             :                         // do not record deletion of Format!
    1299             :                         ::sw::UndoGuard const ug(
    1300           0 :                                 pFmt->GetDoc()->GetIDocumentUndoRedo());
    1301           0 :                         DestroyAttr(pAttr);
    1302           0 :                         return false; // text node full :(
    1303             :                     }
    1304        6598 :                     nInsMode |= nsSetAttrMode::SETATTR_NOTXTATRCHR;
    1305             : 
    1306       19834 :                     if (pAnchor &&
    1307       13156 :                         (FLY_AS_CHAR == pAnchor->GetAnchorId()) &&
    1308       19674 :                         pAnchor->GetCntntAnchor() &&
    1309       38068 :                         pAnchor->GetCntntAnchor()->nNode == *this &&
    1310        5198 :                         pAnchor->GetCntntAnchor()->nContent == aIdx )
    1311             :                     {
    1312             :                         const_cast<SwIndex&>(
    1313        5082 :                             pAnchor->GetCntntAnchor()->nContent)--;
    1314        6598 :                     }
    1315             :                 }
    1316        6880 :                 pFly->SetAnchor( this );
    1317             : 
    1318             :                 // Format-Pointer kann sich im SetAnchor geaendert haben!
    1319             :                 // (Kopieren in andere Docs!)
    1320        6880 :                 pFmt = pAttr->GetFlyCnt().GetFrmFmt();
    1321        6880 :                 SwDoc *pDoc = pFmt->GetDoc();
    1322             : 
    1323             :                 // OD 26.06.2003 #108784# - allow drawing objects in header/footer.
    1324             :                 // But don't allow control objects in header/footer
    1325       12204 :                 if( RES_DRAWFRMFMT == pFmt->Which() &&
    1326        5324 :                     pDoc->IsInHeaderFooter( pFmt->GetAnchor().GetCntntAnchor()->nNode ) )
    1327             :                 {
    1328             :                     SwDrawContact* pDrawContact =
    1329         220 :                         static_cast<SwDrawContact*>(pFmt->FindContactObj());
    1330         434 :                     if ( pDrawContact &&
    1331         434 :                          pDrawContact->GetMaster() &&
    1332         214 :                          ::CheckControlLayer( pDrawContact->GetMaster() ) )
    1333             :                     {
    1334             :                         // das soll nicht meoglich sein; hier verhindern
    1335             :                         // Der Dtor des TxtHints loescht nicht das Zeichen.
    1336             :                         // Wenn ein CH_TXTATR_.. vorliegt, dann muss man
    1337             :                         // dieses explizit loeschen
    1338           0 :                         if( nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode )
    1339             :                         {
    1340             :                             // loesche das Zeichen aus dem String !
    1341             :                             OSL_ENSURE( ( CH_TXTATR_BREAKWORD ==
    1342             :                                         m_Text[pAttr->GetStart()] ||
    1343             :                                       CH_TXTATR_INWORD ==
    1344             :                                         m_Text[pAttr->GetStart()]),
    1345             :                                     "where is my attribute character?" );
    1346           0 :                             m_Text = m_Text.replaceAt(pAttr->GetStart(), 1, "");
    1347             :                             // Indizies Updaten
    1348           0 :                             SwIndex aTmpIdx( this, pAttr->GetStart() );
    1349           0 :                             Update( aTmpIdx, 1, true );
    1350             :                         }
    1351             :                         // do not record deletion of Format!
    1352           0 :                         ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
    1353           0 :                         DestroyAttr( pAttr );
    1354           0 :                         return false;
    1355             :                     }
    1356             :                 }
    1357        6880 :                 break;
    1358             :             }
    1359             : 
    1360             :         case RES_TXTATR_FTN :
    1361             :             {
    1362             :                 // Fussnoten, man kommt an alles irgendwie heran.
    1363             :                 // CntntNode erzeugen und in die Inserts-Section stellen
    1364         272 :                 SwDoc *pDoc = GetDoc();
    1365         272 :                 SwNodes &rNodes = pDoc->GetNodes();
    1366             : 
    1367             :                 // FussNote in nicht Content-/Redline-Bereich einfuegen ??
    1368         272 :                 if( StartOfSectionIndex() < rNodes.GetEndOfAutotext().GetIndex() )
    1369             :                 {
    1370             :                     // das soll nicht meoglich sein; hier verhindern
    1371             :                     // Der Dtor des TxtHints loescht nicht das Zeichen.
    1372             :                     // Wenn ein CH_TXTATR_.. vorliegt, dann muss man
    1373             :                     // dieses explizit loeschen
    1374           0 :                     if( nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode )
    1375             :                     {
    1376             :                         // loesche das Zeichen aus dem String !
    1377             :                         OSL_ENSURE( ( CH_TXTATR_BREAKWORD ==
    1378             :                                       m_Text[pAttr->GetStart()] ||
    1379             :                                   CH_TXTATR_INWORD ==
    1380             :                                       m_Text[pAttr->GetStart()]),
    1381             :                                 "where is my attribute character?" );
    1382           0 :                         m_Text = m_Text.replaceAt(pAttr->GetStart(), 1, "");
    1383             :                         // Indizies Updaten
    1384           0 :                         SwIndex aTmpIdx( this, pAttr->GetStart() );
    1385           0 :                         Update( aTmpIdx, 1, true );
    1386             :                     }
    1387           0 :                     DestroyAttr( pAttr );
    1388           0 :                     return false;
    1389             :                 }
    1390             : 
    1391             :                 // wird eine neue Fussnote eingefuegt ??
    1392         272 :                 bool bNewFtn = 0 == ((SwTxtFtn*)pAttr)->GetStartNode();
    1393         272 :                 if( bNewFtn )
    1394             :                 {
    1395         268 :                     ((SwTxtFtn*)pAttr)->MakeNewTextSection( GetNodes() );
    1396         268 :                     SwRegHistory* pHist = GetpSwpHints()
    1397         268 :                         ? GetpSwpHints()->GetHistory() : 0;
    1398         268 :                     if( pHist )
    1399          40 :                         pHist->ChangeNodeIndex( GetIndex() );
    1400             :                 }
    1401           4 :                 else if ( !GetpSwpHints() || !GetpSwpHints()->IsInSplitNode() )
    1402             :                 {
    1403             :                     // loesche alle Frames der Section, auf die der StartNode zeigt
    1404             :                     sal_uLong nSttIdx =
    1405           4 :                         ((SwTxtFtn*)pAttr)->GetStartNode()->GetIndex();
    1406           4 :                     sal_uLong nEndIdx = rNodes[ nSttIdx++ ]->EndOfSectionIndex();
    1407             :                     SwCntntNode* pCNd;
    1408           8 :                     for( ; nSttIdx < nEndIdx; ++nSttIdx )
    1409           4 :                         if( 0 != ( pCNd = rNodes[ nSttIdx ]->GetCntntNode() ))
    1410           4 :                             pCNd->DelFrms();
    1411             :                 }
    1412             : 
    1413         272 :                 if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
    1414             :                 {
    1415             :                     // Wir muessen zuerst einfuegen, da sonst gleiche Indizes
    1416             :                     // entstehen koennen und das Attribut im _SortArr_ am
    1417             :                     // Dokument nicht eingetrage wird.
    1418         268 :                     SwIndex aNdIdx( this, pAttr->GetStart() );
    1419         536 :                     const OUString c(GetCharOfTxtAttr(*pAttr));
    1420         536 :                     OUString const ins( InsertText(c, aNdIdx, nInsertFlags) );
    1421         268 :                     if (ins.isEmpty())
    1422             :                     {
    1423           0 :                         DestroyAttr(pAttr);
    1424           0 :                         return false; // text node full :(
    1425             :                     }
    1426         536 :                     nInsMode |= nsSetAttrMode::SETATTR_NOTXTATRCHR;
    1427             :                 }
    1428             : 
    1429             :                 // Wir tragen uns am FtnIdx-Array des Docs ein ...
    1430         272 :                 SwTxtFtn* pTxtFtn = 0;
    1431         272 :                 if( !bNewFtn )
    1432             :                 {
    1433             :                     // eine alte Ftn wird umgehaengt (z.B. SplitNode)
    1434           4 :                     for( size_t n = 0; n < pDoc->GetFtnIdxs().size(); ++n )
    1435           4 :                         if( pAttr == pDoc->GetFtnIdxs()[n] )
    1436             :                         {
    1437             :                             // neuen Index zuweisen, dafuer aus dem SortArray
    1438             :                             // loeschen und neu eintragen
    1439           4 :                             pTxtFtn = pDoc->GetFtnIdxs()[n];
    1440           4 :                             pDoc->GetFtnIdxs().erase( pDoc->GetFtnIdxs().begin() + n );
    1441           4 :                             break;
    1442             :                         }
    1443             :                         // wenn ueber Undo der StartNode gesetzt wurde, kann
    1444             :                         // der Index noch gar nicht in der Verwaltung stehen !!
    1445             :                 }
    1446         272 :                 if( !pTxtFtn )
    1447         268 :                     pTxtFtn = (SwTxtFtn*)pAttr;
    1448             : 
    1449             :                 // fuers Update der Nummern und zum Sortieren
    1450             :                 // muss der Node gesetzt sein.
    1451         272 :                 ((SwTxtFtn*)pAttr)->ChgTxtNode( this );
    1452             : 
    1453             :                 // FussNote im Redline-Bereich NICHT ins FtnArray einfuegen!
    1454         272 :                 if( StartOfSectionIndex() > rNodes.GetEndOfRedlines().GetIndex() )
    1455             :                 {
    1456         272 :                     const bool bSuccess = pDoc->GetFtnIdxs().insert(pTxtFtn).second;
    1457             :                     OSL_ENSURE( bSuccess, "FtnIdx not inserted." );
    1458             :                     (void) bSuccess; // unused in non-debug
    1459             :                 }
    1460         272 :                 SwNodeIndex aTmpIndex( *this );
    1461         272 :                 pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex);
    1462         272 :                 ((SwTxtFtn*)pAttr)->SetSeqRefNo();
    1463             :             }
    1464         272 :             break;
    1465             : 
    1466             :             case RES_TXTATR_FIELD:
    1467             :                 {
    1468             :                     // fuer HiddenParaFields Benachrichtigungsmechanismus
    1469             :                     // anwerfen
    1470        2740 :                     if( RES_HIDDENPARAFLD == pAttr->GetFmtFld().GetField()->GetTyp()->Which() )
    1471             :                     {
    1472           0 :                         bHiddenPara = true;
    1473             :                     }
    1474             :                 }
    1475        2740 :                 break;
    1476             : 
    1477             :         }
    1478             :         // Fuer SwTxtHints ohne Endindex werden CH_TXTATR_..
    1479             :         // eingefuegt, aStart muss danach um einen zurueckgesetzt werden.
    1480             :         // Wenn wir im SwTxtNode::Copy stehen, so wurde das Zeichen bereits
    1481             :         // mitkopiert. In solchem Fall ist SETATTR_NOTXTATRCHR angegeben worden.
    1482       10648 :         if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
    1483             :         {
    1484        2600 :             SwIndex aIdx( this, pAttr->GetStart() );
    1485        2600 :             OUString const ins( InsertText(OUString(GetCharOfTxtAttr(*pAttr)),
    1486        5200 :                         aIdx, nInsertFlags) );
    1487        2600 :             if (ins.isEmpty())
    1488             :             {
    1489           0 :                 DestroyAttr(pAttr);
    1490           0 :                 return false; // text node full :(
    1491             :             }
    1492             : 
    1493             :             // adjust end of hint to account for inserted CH_TXTATR
    1494        2600 :             sal_Int32 * const pEnd(pAttr->GetEnd());
    1495        2600 :             if (pEnd)
    1496             :             {
    1497         194 :                 *pEnd = *pEnd + 1;
    1498        2600 :             }
    1499             :         }
    1500             :     }
    1501             : 
    1502             :     // handle attributes which provide content
    1503      157690 :     sal_Int32 nEnd = nStart;
    1504      157690 :     bool bInputFieldStartCharInserted = false;
    1505      157690 :     bool bInputFieldEndCharInserted = false;
    1506      157690 :     const bool bHasContent( pAttr->HasContent() );
    1507      157690 :     if ( bHasContent )
    1508             :     {
    1509          28 :         switch( pAttr->Which() )
    1510             :         {
    1511             :         case RES_TXTATR_INPUTFIELD:
    1512             :             {
    1513          28 :                 SwTxtInputFld* pTxtInputFld = dynamic_cast<SwTxtInputFld*>(pAttr);
    1514          28 :                 if ( pTxtInputFld )
    1515             :                 {
    1516          28 :                     if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nMode) )
    1517             :                     {
    1518          20 :                         SwIndex aIdx( this, pAttr->GetStart() );
    1519          20 :                         InsertText( OUString(CH_TXT_ATR_INPUTFIELDSTART), aIdx, nInsertFlags );
    1520          40 :                         const OUString aContent = pTxtInputFld->GetFieldContent();
    1521          20 :                         InsertText( aContent, aIdx, nInsertFlags );
    1522          20 :                         InsertText( OUString(CH_TXT_ATR_INPUTFIELDEND), aIdx, nInsertFlags );
    1523             : 
    1524          20 :                         sal_Int32* const pEnd(pAttr->GetEnd());
    1525             :                         OSL_ENSURE( pEnd != NULL, "<SwTxtNode::InsertHint(..)> - missing end of RES_TXTATR_INPUTFIELD!" );
    1526          20 :                         if ( pEnd != NULL )
    1527             :                         {
    1528          20 :                             *pEnd = *pEnd + 2 + aContent.getLength();
    1529          20 :                             nEnd = *pEnd;
    1530          20 :                         }
    1531             :                     }
    1532             :                     else
    1533             :                     {
    1534             :                         // assure that CH_TXT_ATR_INPUTFIELDSTART and CH_TXT_ATR_INPUTFIELDEND are inserted.
    1535           8 :                         if ( m_Text[ pAttr->GetStart() ] != CH_TXT_ATR_INPUTFIELDSTART )
    1536             :                         {
    1537           0 :                             SwIndex aIdx( this, pAttr->GetStart() );
    1538           0 :                             InsertText( OUString(CH_TXT_ATR_INPUTFIELDSTART), aIdx, nInsertFlags );
    1539           0 :                             bInputFieldStartCharInserted = true;
    1540           0 :                             sal_Int32* const pEnd(pAttr->GetEnd());
    1541             :                             OSL_ENSURE( pEnd != NULL, "<SwTxtNode::InsertHint(..)> - missing end of RES_TXTATR_INPUTFIELD!" );
    1542           0 :                             if ( pEnd != NULL )
    1543             :                             {
    1544           0 :                                 *pEnd = *pEnd + 1;
    1545           0 :                                 nEnd = *pEnd;
    1546           0 :                             }
    1547             :                         }
    1548             : 
    1549           8 :                         sal_Int32* const pEnd(pAttr->GetEnd());
    1550             :                         OSL_ENSURE( pEnd != NULL, "<SwTxtNode::InsertHint(..)> - missing end of RES_TXTATR_INPUTFIELD!" );
    1551           8 :                         if ( pEnd != NULL
    1552           8 :                              && m_Text[ *(pEnd) - 1 ] != CH_TXT_ATR_INPUTFIELDEND )
    1553             :                         {
    1554           0 :                             SwIndex aIdx( this, *(pEnd) );
    1555           0 :                             InsertText( OUString(CH_TXT_ATR_INPUTFIELDEND), aIdx, nInsertFlags );
    1556           0 :                             bInputFieldEndCharInserted = true;
    1557           0 :                             *pEnd = *pEnd + 1;
    1558           0 :                             nEnd = *pEnd;
    1559             :                         }
    1560             :                     }
    1561             :                 }
    1562             :             }
    1563          28 :             break;
    1564             :         default:
    1565           0 :             break;
    1566             :         }
    1567             :     }
    1568             : 
    1569      157690 :     GetOrCreateSwpHints();
    1570             : 
    1571             :     // handle overlap with an existing InputField
    1572      157690 :     bool bInsertHint = true;
    1573             :     {
    1574      157690 :         const SwTxtInputFld* pTxtInputFld = GetOverlappingInputFld( *pAttr );
    1575      157690 :         if ( pTxtInputFld != NULL )
    1576             :         {
    1577           0 :             if ( pAttr->End() == NULL )
    1578             :             {
    1579           0 :                 bInsertHint = false;
    1580             :             }
    1581             :             else
    1582             :             {
    1583           0 :                 if ( pAttr->GetStart() > pTxtInputFld->GetStart() )
    1584             :                 {
    1585           0 :                     pAttr->GetStart() = pTxtInputFld->GetStart();
    1586             :                 }
    1587           0 :                 if ( *(pAttr->End()) < *(pTxtInputFld->End()) )
    1588             :                 {
    1589           0 :                     *(pAttr->GetEnd()) = *(pTxtInputFld->End());
    1590             :                 }
    1591             :             }
    1592             :         }
    1593             :     }
    1594             : 
    1595             :     // 4263: AttrInsert durch TextInsert => kein Adjust
    1596             :     const bool bRet = bInsertHint
    1597      157690 :                       ? m_pSwpHints->TryInsertHint( pAttr, *this, nMode )
    1598      315380 :                       : false;
    1599             : 
    1600      157690 :     if ( !bRet )
    1601             :     {
    1602           4 :         if ( bDummyChar
    1603           4 :              && !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nMode) )
    1604             :         {
    1605             :             // undo insertion of dummy character
    1606             :             // N.B. cannot insert the dummy character after inserting the hint,
    1607             :             // because if the hint has no extent it will be moved in InsertText,
    1608             :             // resulting in infinite recursion
    1609             :             OSL_ENSURE( ( CH_TXTATR_BREAKWORD == m_Text[nStart] ||
    1610             :                           CH_TXTATR_INWORD    == m_Text[nStart] ),
    1611             :                     "where is my attribute character?" );
    1612           4 :             SwIndex aIdx( this, nStart );
    1613           4 :             EraseText( aIdx, 1 );
    1614             :         }
    1615             : 
    1616           4 :         if ( bHasContent )
    1617             :         {
    1618           0 :             if ( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nMode)
    1619           0 :                  && (nEnd - nStart) > 0 )
    1620             :             {
    1621           0 :                 SwIndex aIdx( this, nStart );
    1622           0 :                 EraseText( aIdx, (nEnd - nStart) );
    1623             :             }
    1624             :             else
    1625             :             {
    1626           0 :                 if ( bInputFieldEndCharInserted
    1627           0 :                      && (nEnd - nStart) > 0 )
    1628             :                 {
    1629           0 :                     SwIndex aIdx( this, nEnd - 1 );
    1630           0 :                     EraseText( aIdx, 1 );
    1631             :                 }
    1632             : 
    1633           0 :                 if ( bInputFieldStartCharInserted )
    1634             :                 {
    1635           0 :                     SwIndex aIdx( this, nStart );
    1636           0 :                     EraseText( aIdx, 1 );
    1637             :                 }
    1638             :             }
    1639             :         }
    1640             :     }
    1641             : 
    1642      157690 :     if ( bHiddenPara )
    1643             :     {
    1644           0 :         SetCalcHiddenParaField();
    1645             :     }
    1646             : 
    1647      157690 :     return bRet;
    1648             : }
    1649             : 
    1650          10 : void SwTxtNode::DeleteAttribute( SwTxtAttr * const pAttr )
    1651             : {
    1652          10 :     if ( !HasHints() )
    1653             :     {
    1654             :         OSL_FAIL("DeleteAttribute called, but text node without hints?");
    1655          10 :         return;
    1656             :     }
    1657             : 
    1658          10 :     if ( pAttr->HasDummyChar() )
    1659             :     {
    1660             :         // Unbedingt Copy-konstruieren!
    1661          10 :         const SwIndex aIdx( this, pAttr->GetStart() );
    1662             :         // erase the CH_TXTATR, which will also delete pAttr
    1663          10 :         EraseText( aIdx, 1 );
    1664             :     }
    1665           0 :     else if ( pAttr->HasContent() )
    1666             :     {
    1667           0 :         const SwIndex aIdx( this, pAttr->GetStart() );
    1668             :         OSL_ENSURE( pAttr->End() != NULL, "<SwTxtNode::DeleteAttribute(..)> - missing End() at <SwTxtAttr> instance which has content" );
    1669           0 :         EraseText( aIdx, *pAttr->End() - pAttr->GetStart() );
    1670             :     }
    1671             :     else
    1672             :     {
    1673             :         // create MsgHint before start/end become invalid
    1674             :         SwUpdateAttr aHint(
    1675           0 :             pAttr->GetStart(),
    1676           0 :             *pAttr->GetEnd(),
    1677           0 :             pAttr->Which());
    1678             : 
    1679           0 :         m_pSwpHints->Delete( pAttr );
    1680           0 :         SwTxtAttr::Destroy( pAttr, GetDoc()->GetAttrPool() );
    1681           0 :         NotifyClients( 0, &aHint );
    1682             : 
    1683           0 :         TryDeleteSwpHints();
    1684             :     }
    1685             : }
    1686             : 
    1687             : //FIXME: this does NOT respect SORT NUMBER (for CHARFMT)!
    1688        4316 : void SwTxtNode::DeleteAttributes(
    1689             :     const sal_uInt16 nWhich,
    1690             :     const sal_Int32 nStart,
    1691             :     const sal_Int32 nEnd )
    1692             : {
    1693        4316 :     if ( !HasHints() )
    1694        4316 :         return;
    1695             : 
    1696        9124 :     for ( size_t nPos = 0; m_pSwpHints && nPos < m_pSwpHints->Count(); ++nPos )
    1697             :     {
    1698        4858 :         SwTxtAttr * const pTxtHt = m_pSwpHints->GetTextHint( nPos );
    1699        4858 :         const sal_Int32 nHintStart = pTxtHt->GetStart();
    1700        4858 :         if (nStart < nHintStart)
    1701             :         {
    1702          50 :             break; // sorted by start
    1703             :         }
    1704        4808 :         else if ( (nStart == nHintStart) && (nWhich == pTxtHt->Which()) )
    1705             :         {
    1706        4316 :             if ( nWhich == RES_CHRATR_HIDDEN  )
    1707             :             {
    1708             :                 OSL_FAIL("hey, that's a CHRATR! how did that get in?");
    1709           0 :                 SetCalcHiddenCharFlags();
    1710             :             }
    1711        4316 :             else if ( nWhich == RES_TXTATR_CHARFMT )
    1712             :             {
    1713             :                 // Check if character format contains hidden attribute:
    1714           0 :                 const SwCharFmt* pFmt = pTxtHt->GetCharFmt().GetCharFmt();
    1715             :                 const SfxPoolItem* pItem;
    1716           0 :                 if ( SfxItemState::SET == pFmt->GetItemState( RES_CHRATR_HIDDEN, true, &pItem ) )
    1717           0 :                     SetCalcHiddenCharFlags();
    1718             :             }
    1719             :             // #i75430# Recalc hidden flags if necessary
    1720        4316 :             else if ( nWhich == RES_TXTATR_AUTOFMT )
    1721             :             {
    1722             :                 // Check if auto style contains hidden attribute:
    1723           0 :                 const SfxPoolItem* pHiddenItem = CharFmt::GetItem( *pTxtHt, RES_CHRATR_HIDDEN );
    1724           0 :                 if ( pHiddenItem )
    1725           0 :                     SetCalcHiddenCharFlags();
    1726             :                 // for auto styles DeleteAttributes is only called from Undo
    1727             :                 // so it shouldn't need to care about ignore start/end flags
    1728             :             }
    1729             : 
    1730        4316 :             sal_Int32 const * const pEndIdx = pTxtHt->GetEnd();
    1731             : 
    1732        4316 :             if ( pTxtHt->HasDummyChar() )
    1733             :             {
    1734             :                 // Unbedingt Copy-konstruieren!
    1735        4316 :                 const SwIndex aIdx( this, nStart );
    1736             :                 // erase the CH_TXTATR, which will also delete pTxtHt
    1737        4316 :                 EraseText( aIdx, 1 );
    1738             :             }
    1739           0 :             else if ( pTxtHt->HasContent() )
    1740             :             {
    1741           0 :                 const SwIndex aIdx( this, nStart );
    1742             :                 OSL_ENSURE( pTxtHt->End() != NULL, "<SwTxtNode::DeleteAttributes(..)> - missing End() at <SwTxtAttr> instance which has content" );
    1743           0 :                 EraseText( aIdx, *pTxtHt->End() - nStart );
    1744             :             }
    1745           0 :             else if( *pEndIdx == nEnd )
    1746             :             {
    1747             :                 // den MsgHint jetzt fuettern, weil gleich sind
    1748             :                 // Start und End weg.
    1749             :                 // Das CalcVisibleFlag bei HiddenParaFields entfaellt,
    1750             :                 // da dies das Feld im Dtor selbst erledigt.
    1751             :                 SwUpdateAttr aHint(
    1752             :                     nStart,
    1753             :                     *pEndIdx,
    1754           0 :                     nWhich);
    1755             : 
    1756           0 :                 m_pSwpHints->DeleteAtPos( nPos );    // gefunden, loeschen,
    1757           0 :                 SwTxtAttr::Destroy( pTxtHt, GetDoc()->GetAttrPool() );
    1758           0 :                 NotifyClients( 0, &aHint );
    1759             :             }
    1760             :         }
    1761             :     }
    1762        4316 :     TryDeleteSwpHints();
    1763             : }
    1764             : 
    1765           0 : void SwTxtNode::DelSoftHyph( const sal_Int32 nStt, const sal_Int32 nEnd )
    1766             : {
    1767           0 :     sal_Int32 nFndPos = nStt;
    1768           0 :     sal_Int32 nEndPos = nEnd;
    1769             :     for (;;)
    1770             :     {
    1771           0 :         nFndPos = m_Text.indexOf(CHAR_SOFTHYPHEN, nFndPos);
    1772           0 :         if (nFndPos<0 || nFndPos>=nEndPos )
    1773             :         {
    1774             :             break;
    1775             :         }
    1776           0 :         const SwIndex aIdx( this, nFndPos );
    1777           0 :         EraseText( aIdx, 1 );
    1778           0 :         --nEndPos;
    1779           0 :     }
    1780           0 : }
    1781             : 
    1782             : //In MS Word, the font underline setting of the paragraph end position wont affect the formatting of numbering, so we ignore it
    1783          14 : bool lcl_IsIgnoredCharFmtForNumbering(const sal_uInt16 nWhich)
    1784             : {
    1785          14 :     return (nWhich ==  RES_CHRATR_UNDERLINE || nWhich == RES_CHRATR_BACKGROUND || nWhich == RES_CHRATR_ESCAPEMENT);
    1786             : }
    1787             : 
    1788             : //In MS Word, following properties of the paragraph end position wont affect the formatting of bullets, so we ignore them:
    1789             : //Font underline;
    1790             : //Font Italic of Western, CJK and CTL;
    1791             : //Font Bold of Wertern, CJK and CTL;
    1792         110 : bool lcl_IsIgnoredCharFmtForBullets(const sal_uInt16 nWhich)
    1793             : {
    1794         110 :     return (nWhich == RES_CHRATR_UNDERLINE || nWhich == RES_CHRATR_POSTURE || nWhich == RES_CHRATR_WEIGHT
    1795         100 :         || nWhich == RES_CHRATR_CJK_POSTURE || nWhich == RES_CHRATR_CJK_WEIGHT
    1796         200 :         || nWhich == RES_CHRATR_CTL_POSTURE || nWhich == RES_CHRATR_CTL_WEIGHT);
    1797             : }
    1798             : 
    1799             : //Condition for expanding char set to character style of specified number rule level:
    1800             : //The item inside the set should not conflict to any exist and non-default item inside paragraph properties set (SwCntntNode::SwPAttrSet);
    1801             : //The node should have applied a number rule;
    1802             : //The node should be counted in a list, if not, make it to be;
    1803             : //The item should not conflict to any exist and non-default item inside the character of specified number rule level;
    1804             : //The item should not be ignored depend on the exact number rule type;
    1805       10530 : bool SwTxtNode::TryCharSetExpandToNum(const SfxItemSet& aCharSet)
    1806             : {
    1807       10530 :     bool bRet = false;
    1808       10530 :     SfxItemIter aIter( aCharSet );
    1809       10530 :         const SfxPoolItem* pItem = aIter.FirstItem();
    1810       10530 :         const sal_uInt16 nWhich = pItem->Which();
    1811             : 
    1812       10530 :     const SfxPoolItem& rInnerItem = GetAttr(nWhich,false);
    1813             : 
    1814       10530 :     if (!IsDefaultItem(&rInnerItem) &&  !IsInvalidItem(&rInnerItem))
    1815        8644 :         return bRet;
    1816             : 
    1817        1886 :     if (!IsInList() && GetNumRule() && !GetListId().isEmpty())
    1818             :     {
    1819           0 :         return bRet;
    1820             :     }
    1821             : 
    1822        1886 :     SwNumRule* pCurrNum = GetNumRule(false);
    1823             : 
    1824        1886 :     int nLevel = GetActualListLevel();
    1825             : 
    1826        1886 :     if (nLevel != -1 && pCurrNum)
    1827             :     {
    1828         124 :         const SwNumFmt* pCurrNumFmt = pCurrNum->GetNumFmt(static_cast<sal_uInt16>(nLevel));
    1829         124 :         if (pCurrNumFmt)
    1830             :         {
    1831         124 :             if (pCurrNumFmt->IsItemize() && lcl_IsIgnoredCharFmtForBullets(nWhich))
    1832          30 :                 return bRet;
    1833          94 :             if (pCurrNumFmt->IsEnumeration() && lcl_IsIgnoredCharFmtForNumbering(nWhich))
    1834           2 :                 return bRet;
    1835          92 :             SwCharFmt* pCurrCharFmt =pCurrNumFmt->GetCharFmt();
    1836             : 
    1837          92 :             if (pCurrCharFmt && pCurrCharFmt->GetItemState(nWhich,false) != SfxItemState::SET)
    1838             :             {
    1839          20 :                 pCurrCharFmt->SetFmtAttr(*pItem);
    1840          20 :                 SwNumFmt aNewNumFmt(*pCurrNumFmt);
    1841          20 :                 aNewNumFmt.SetCharFmt(pCurrCharFmt);
    1842          20 :                 pCurrNum->Set(nLevel,aNewNumFmt);
    1843          20 :                 bRet = true;
    1844             :             }
    1845             :         }
    1846             :     }
    1847             : 
    1848        1854 :     return bRet;
    1849             : }
    1850             : 
    1851             : // setze diese Attribute am TextNode. Wird der gesamte Bereich umspannt,
    1852             : // dann setze sie nur im AutoAttrSet (SwCntntNode:: SetAttr)
    1853      192028 : bool SwTxtNode::SetAttr(
    1854             :     const SfxItemSet& rSet,
    1855             :     const sal_Int32 nStt,
    1856             :     const sal_Int32 nEnd,
    1857             :     const SetAttrMode nMode )
    1858             : {
    1859      192028 :     if( !rSet.Count() )
    1860           0 :         return false;
    1861             : 
    1862             :     // teil die Sets auf (fuer Selektion in Nodes)
    1863      192028 :     const SfxItemSet* pSet = &rSet;
    1864      192028 :     SfxItemSet aTxtSet( *rSet.GetPool(), RES_TXTATR_BEGIN, RES_TXTATR_END-1 );
    1865             : 
    1866             :     // gesamter Bereich
    1867      266564 :     if ( !nStt && (nEnd == m_Text.getLength()) &&
    1868       74536 :          !(nMode & nsSetAttrMode::SETATTR_NOFORMATATTR ) )
    1869             :     {
    1870             :         // sind am Node schon Zeichenvorlagen gesetzt, muss man diese Attribute
    1871             :         // (rSet) immer als TextAttribute setzen, damit sie angezeigt werden.
    1872       54136 :         bool bHasCharFmts = false;
    1873       54136 :         if ( HasHints() )
    1874             :         {
    1875       27896 :             for ( size_t n = 0; n < m_pSwpHints->Count(); ++n )
    1876             :             {
    1877       17478 :                 if ( (*m_pSwpHints)[ n ]->IsCharFmtAttr() )
    1878             :                 {
    1879         782 :                     bHasCharFmts = true;
    1880         782 :                     break;
    1881             :                 }
    1882             :             }
    1883             :         }
    1884             : 
    1885       54136 :         if( !bHasCharFmts )
    1886             :         {
    1887       53354 :             aTxtSet.Put( rSet );
    1888             :             // If there are any character attributes in rSet,
    1889             :             // we want to set them at the paragraph:
    1890       53354 :             if( aTxtSet.Count() != rSet.Count() )
    1891             :             {
    1892       47764 :                 const bool bRet = SetAttr( rSet );
    1893       47764 :                 if( !aTxtSet.Count() )
    1894       98246 :                     return bRet;
    1895             :             }
    1896             : 
    1897             :             // check for auto style:
    1898             :             const SfxPoolItem* pItem;
    1899        5706 :             const bool bAutoStyle = SfxItemState::SET == aTxtSet.GetItemState( RES_TXTATR_AUTOFMT, false, &pItem );
    1900        5706 :             if ( bAutoStyle )
    1901             :             {
    1902        2950 :                 boost::shared_ptr<SfxItemSet> pAutoStyleSet = static_cast<const SwFmtAutoFmt*>(pItem)->GetStyleHandle();
    1903        2950 :                 const bool bRet = SetAttr( *pAutoStyleSet );
    1904        2950 :                 if( 1 == aTxtSet.Count() )
    1905        2950 :                     return bRet;
    1906             :             }
    1907             : 
    1908             :             // Continue with the text attributes:
    1909        2756 :             pSet = &aTxtSet;
    1910             :         }
    1911             :     }
    1912             : 
    1913      141430 :     GetOrCreateSwpHints();
    1914             : 
    1915      282860 :     SfxItemSet aCharSet( *rSet.GetPool(), aCharAutoFmtSetRange );
    1916             : 
    1917      141430 :     size_t nCount = 0;
    1918      282860 :     SfxItemIter aIter( *pSet );
    1919      141430 :     const SfxPoolItem* pItem = aIter.GetCurItem();
    1920             : 
    1921             :     do
    1922             :     {
    1923      430576 :         if ( pItem && (reinterpret_cast<SfxPoolItem*>(-1) != pItem))
    1924             :         {
    1925      430576 :             const sal_uInt16 nWhich = pItem->Which();
    1926             :             OSL_ENSURE( isCHRATR(nWhich) || isTXTATR(nWhich),
    1927             :                     "SwTxtNode::SetAttr(): unknown attribute" );
    1928      430576 :             if ( isCHRATR(nWhich) || isTXTATR(nWhich) )
    1929             :             {
    1930      442518 :                 if ((RES_TXTATR_CHARFMT == nWhich) &&
    1931       11942 :                     (GetDoc()->GetDfltCharFmt() ==
    1932       11942 :                      static_cast<const SwFmtCharFmt*>(pItem)->GetCharFmt()))
    1933             :                 {
    1934           0 :                     SwIndex aIndex( this, nStt );
    1935           0 :                     RstTxtAttr( aIndex, nEnd - nStt, RES_TXTATR_CHARFMT, 0 );
    1936           0 :                     DontExpandFmt( aIndex );
    1937             :                 }
    1938             :                 else
    1939             :                 {
    1940      430576 :                     if (isCHRATR(nWhich) ||
    1941             :                         (RES_TXTATR_UNKNOWN_CONTAINER == nWhich))
    1942             :                     {
    1943      408946 :                         aCharSet.Put( *pItem );
    1944             :                     }
    1945             :                     else
    1946             :                     {
    1947             : 
    1948       21630 :                         SwTxtAttr *const pNew = MakeTxtAttr( *GetDoc(),
    1949       21630 :                                 const_cast<SfxPoolItem&>(*pItem), nStt, nEnd );
    1950       21630 :                         if ( pNew )
    1951             :                         {
    1952       21630 :                             if ( nEnd != nStt && !pNew->GetEnd() )
    1953             :                             {
    1954             :                                 OSL_FAIL("Attribut without end, but area marked");
    1955           0 :                                 DestroyAttr( pNew ); // do not insert
    1956             :                             }
    1957       21630 :                             else if ( InsertHint( pNew, nMode ) )
    1958             :                             {
    1959       21626 :                                 ++nCount;
    1960             :                             }
    1961             :                         }
    1962             :                     }
    1963             :                 }
    1964             :             }
    1965             :         }
    1966      430576 :         if ( aIter.IsAtEnd() )
    1967      141430 :             break;
    1968      289146 :         pItem = aIter.NextItem();
    1969             :     } while( true );
    1970             : 
    1971      141430 :     if ( aCharSet.Count() )
    1972             :     {
    1973      121928 :         SwTxtAttr* pTmpNew = MakeTxtAttr( *GetDoc(), aCharSet, nStt, nEnd );
    1974      121928 :         if ( InsertHint( pTmpNew, nMode ) )
    1975             :         {
    1976      121928 :             ++nCount;
    1977             :         }
    1978             :     }
    1979             : 
    1980      141430 :     TryDeleteSwpHints();
    1981             : 
    1982      333458 :     return nCount != 0;
    1983             : }
    1984             : 
    1985        9010 : static void lcl_MergeAttr( SfxItemSet& rSet, const SfxPoolItem& rAttr )
    1986             : {
    1987        9010 :     if ( RES_TXTATR_AUTOFMT == rAttr.Which() )
    1988             :     {
    1989        8192 :         const SfxItemSet* pCFSet = CharFmt::GetItemSet( rAttr );
    1990        8192 :         if ( !pCFSet )
    1991        9010 :             return;
    1992        8192 :         SfxWhichIter aIter( *pCFSet );
    1993        8192 :         sal_uInt16 nWhich = aIter.FirstWhich();
    1994      401404 :         while( nWhich )
    1995             :         {
    1996      401400 :             if( ( nWhich < RES_CHRATR_END ||
    1997      761848 :                   RES_TXTATR_UNKNOWN_CONTAINER == nWhich ) &&
    1998      376828 :                 ( SfxItemState::SET == pCFSet->GetItemState( nWhich, true ) ) )
    1999       57580 :                 rSet.Put( pCFSet->Get( nWhich ) );
    2000      385020 :             nWhich = aIter.NextWhich();
    2001        8192 :         }
    2002             :     }
    2003             :     else
    2004         818 :         rSet.Put( rAttr );
    2005             : }
    2006             : 
    2007      108064 : static void lcl_MergeAttr_ExpandChrFmt( SfxItemSet& rSet, const SfxPoolItem& rAttr )
    2008             : {
    2009      317005 :     if( RES_TXTATR_CHARFMT == rAttr.Which() ||
    2010      207116 :         RES_TXTATR_INETFMT == rAttr.Which() ||
    2011       99052 :         RES_TXTATR_AUTOFMT == rAttr.Which() )
    2012             :     {
    2013      100195 :         const SfxItemSet* pCFSet = CharFmt::GetItemSet( rAttr );
    2014             : 
    2015      100195 :         if ( pCFSet )
    2016             :         {
    2017       99985 :             SfxWhichIter aIter( *pCFSet );
    2018       99985 :             sal_uInt16 nWhich = aIter.FirstWhich();
    2019     4890435 :             while( nWhich )
    2020             :             {
    2021     4881605 :                 if( ( nWhich < RES_CHRATR_END ||
    2022     9463283 :                       ( RES_TXTATR_AUTOFMT == rAttr.Which() && RES_TXTATR_UNKNOWN_CONTAINER == nWhich ) ) &&
    2023     4590480 :                     ( SfxItemState::SET == pCFSet->GetItemState( nWhich, true ) ) )
    2024      473876 :                     rSet.Put( pCFSet->Get( nWhich ) );
    2025     4690465 :                 nWhich = aIter.NextWhich();
    2026       99985 :             }
    2027             :         }
    2028             :     }
    2029             : 
    2030             :     // aufnehmen als MergeWert (falls noch nicht gesetzt neu setzen!)
    2031             : 
    2032             : /* wenn mehrere Attribute ueberlappen gewinnt der letze !!
    2033             :  z.B
    2034             :             1234567890123456789
    2035             :               |------------|        Font1
    2036             :                  |------|           Font2
    2037             :                     ^  ^
    2038             :                     |--|        Abfragebereich: -> Gueltig ist Font2
    2039             : */
    2040      108064 :     rSet.Put( rAttr );
    2041      108064 : }
    2042             : 
    2043             : struct SwPoolItemEndPair
    2044             : {
    2045             : public:
    2046             :     const SfxPoolItem* mpItem;
    2047             :     sal_Int32 mnEndPos;
    2048             : 
    2049      157190 :     SwPoolItemEndPair() : mpItem( 0 ), mnEndPos( 0 ) {};
    2050             : };
    2051             : 
    2052       24868 : static void lcl_MergeListLevelIndentAsLRSpaceItem( const SwTxtNode& rTxtNode,
    2053             :                                             SfxItemSet& rSet )
    2054             : {
    2055       24868 :     if ( rTxtNode.AreListLevelIndentsApplicable() )
    2056             :     {
    2057           0 :         const SwNumRule* pRule = rTxtNode.GetNumRule();
    2058           0 :         if ( pRule && rTxtNode.GetActualListLevel() >= 0 )
    2059             :         {
    2060           0 :             const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(rTxtNode.GetActualListLevel()));
    2061           0 :             if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
    2062             :             {
    2063           0 :                 SvxLRSpaceItem aLR( RES_LR_SPACE );
    2064           0 :                 aLR.SetTxtLeft( rFmt.GetIndentAt() );
    2065           0 :                 aLR.SetTxtFirstLineOfst( static_cast<short>(rFmt.GetFirstLineIndent()) );
    2066           0 :                 rSet.Put( aLR );
    2067             :             }
    2068             :         }
    2069             :     }
    2070       24868 : }
    2071             : 
    2072             : // erfrage die Attribute vom TextNode ueber den Bereich
    2073      334032 : bool SwTxtNode::GetAttr( SfxItemSet& rSet, sal_Int32 nStt, sal_Int32 nEnd,
    2074             :                          const bool bOnlyTxtAttr, const bool bGetFromChrFmt,
    2075             :                          const bool bMergeIndentValuesOfNumRule ) const
    2076             : {
    2077      334032 :     if( HasHints() )
    2078             :     {
    2079             :         /* stelle erstmal fest, welche Text-Attribut in dem Bereich gueltig
    2080             :          * sind. Dabei gibt es folgende Faelle:
    2081             :          *  UnEindeutig wenn: (wenn != Format-Attribut)
    2082             :          *      - das Attribut liegt vollstaendig im Bereich
    2083             :          *      - das Attributende liegt im Bereich
    2084             :          *      - der Attributanfang liegt im Bereich:
    2085             :          * Eindeutig (im Set mergen):
    2086             :          *      - das Attrib umfasst den Bereich
    2087             :          * nichts tun:
    2088             :          *      das Attribut liegt ausserhalb des Bereiches
    2089             :          */
    2090             : 
    2091             :         void (*fnMergeAttr)( SfxItemSet&, const SfxPoolItem& )
    2092             :             = bGetFromChrFmt ? &lcl_MergeAttr_ExpandChrFmt
    2093      143538 :                              : &lcl_MergeAttr;
    2094             : 
    2095             :         // dann besorge mal die Auto-(Fmt)Attribute
    2096      143538 :         SfxItemSet aFmtSet( *rSet.GetPool(), rSet.GetRanges() );
    2097      143538 :         if( !bOnlyTxtAttr )
    2098             :         {
    2099      134866 :             SwCntntNode::GetAttr( aFmtSet );
    2100      134866 :             if ( bMergeIndentValuesOfNumRule )
    2101             :             {
    2102        1440 :                 lcl_MergeListLevelIndentAsLRSpaceItem( *this, aFmtSet );
    2103             :             }
    2104             :         }
    2105             : 
    2106      143538 :         const size_t nSize = m_pSwpHints->Count();
    2107             : 
    2108      143538 :         if( nStt == nEnd )             // kein Bereich:
    2109             :         {
    2110      382943 :             for (size_t n = 0; n < nSize; ++n)
    2111             :             {
    2112      329019 :                 const SwTxtAttr* pHt = (*m_pSwpHints)[n];
    2113      329019 :                 const sal_Int32 nAttrStart = pHt->GetStart();
    2114      329019 :                 if( nAttrStart > nEnd )         // ueber den Bereich hinaus
    2115         118 :                     break;
    2116             : 
    2117      328901 :                 const sal_Int32* pAttrEnd = pHt->End();
    2118      328901 :                 if ( ! pAttrEnd ) // no attributes without end
    2119      236160 :                     continue;
    2120             : 
    2121      159950 :                 if( ( nAttrStart < nStt &&
    2122       69914 :                         ( pHt->DontExpand() ? nStt < *pAttrEnd
    2123      342711 :                                             : nStt <= *pAttrEnd )) ||
    2124       25532 :                     ( nStt == nAttrStart &&
    2125       25900 :                         ( nAttrStart == *pAttrEnd || !nStt )))
    2126       66424 :                     (*fnMergeAttr)( rSet, pHt->GetAttr() );
    2127             :             }
    2128             :         }
    2129             :         else                            // es ist ein Bereich definiert
    2130             :         {
    2131             :             // #i75299#
    2132       89496 :             boost::scoped_ptr< std::vector< SwPoolItemEndPair > > pAttrArr;
    2133             : 
    2134       89496 :             const size_t coArrSz = RES_TXTATR_WITHEND_END - RES_CHRATR_BEGIN;
    2135             : 
    2136      328636 :             for (size_t n = 0; n < nSize; ++n)
    2137             :             {
    2138      239880 :                 const SwTxtAttr* pHt = (*m_pSwpHints)[n];
    2139      239880 :                 const sal_Int32 nAttrStart = pHt->GetStart();
    2140      239880 :                 if( nAttrStart > nEnd )         // ueber den Bereich hinaus
    2141         740 :                     break;
    2142             : 
    2143      239140 :                 const sal_Int32* pAttrEnd = pHt->End();
    2144      239140 :                 if ( ! pAttrEnd ) // no attributes without end
    2145        7042 :                     continue;
    2146             : 
    2147      232098 :                 bool bChkInvalid = false;
    2148      232098 :                 if( nAttrStart <= nStt )       // vor oder genau Start
    2149             :                 {
    2150      187628 :                     if( *pAttrEnd <= nStt )    // liegt davor
    2151      139696 :                         continue;
    2152             : 
    2153       47932 :                     if( nEnd <= *pAttrEnd )     // hinter oder genau Ende
    2154       46398 :                         (*fnMergeAttr)( aFmtSet, pHt->GetAttr() );
    2155             :                     else
    2156             : //                  else if( pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
    2157             :                         // uneindeutig
    2158        1534 :                         bChkInvalid = true;
    2159             :                 }
    2160       44470 :                 else if( nAttrStart < nEnd      // reicht in den Bereich
    2161             : )//                      && pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
    2162        4148 :                     bChkInvalid = true;
    2163             : 
    2164       92402 :                 if( bChkInvalid )
    2165             :                 {
    2166             :                     // uneindeutig ?
    2167        5682 :                     boost::scoped_ptr< SfxItemIter > pItemIter;
    2168        5682 :                     const SfxPoolItem* pItem = 0;
    2169             : 
    2170        5682 :                     if ( RES_TXTATR_AUTOFMT == pHt->Which() )
    2171             :                     {
    2172        4600 :                         const SfxItemSet* pAutoSet = CharFmt::GetItemSet( pHt->GetAttr() );
    2173        4600 :                         if ( pAutoSet )
    2174             :                         {
    2175        4600 :                             pItemIter.reset( new SfxItemIter( *pAutoSet ) );
    2176        4600 :                             pItem = pItemIter->GetCurItem();
    2177             :                         }
    2178             :                     }
    2179             :                     else
    2180        1082 :                         pItem = &pHt->GetAttr();
    2181             : 
    2182        5682 :                     const sal_Int32 nHintEnd = *pAttrEnd;
    2183             : 
    2184       29440 :                     while ( pItem )
    2185             :                     {
    2186       18076 :                         const sal_uInt16 nHintWhich = pItem->Which();
    2187             :                         OSL_ENSURE(!isUNKNOWNATR(nHintWhich),
    2188             :                                 "SwTxtNode::GetAttr(): unknown attribute?");
    2189             : 
    2190       18076 :                         if ( !pAttrArr.get() )
    2191             :                         {
    2192             :                             pAttrArr.reset(
    2193        2858 :                                 new std::vector< SwPoolItemEndPair >(coArrSz));
    2194             :                         }
    2195             : 
    2196       18076 :                         std::vector< SwPoolItemEndPair >::iterator pPrev = pAttrArr->begin();
    2197       19158 :                         if (isCHRATR(nHintWhich) ||
    2198        1082 :                             isTXTATR_WITHEND(nHintWhich))
    2199             :                         {
    2200       18076 :                             pPrev += nHintWhich - RES_CHRATR_BEGIN;
    2201             :                         }
    2202             :                         else
    2203             :                         {
    2204           0 :                             pPrev = pAttrArr->end();
    2205             :                         }
    2206             : 
    2207       18076 :                         if( pPrev != pAttrArr->end() )
    2208             :                         {
    2209       18076 :                             if( !pPrev->mpItem )
    2210             :                             {
    2211        9224 :                                 if ( bOnlyTxtAttr || *pItem != aFmtSet.Get( nHintWhich ) )
    2212             :                                 {
    2213        7552 :                                     if( nAttrStart > nStt )
    2214             :                                     {
    2215        1134 :                                         rSet.InvalidateItem( nHintWhich );
    2216        1134 :                                         pPrev->mpItem = (SfxPoolItem*)-1;
    2217             :                                     }
    2218             :                                     else
    2219             :                                     {
    2220        6418 :                                         pPrev->mpItem = pItem;
    2221        6418 :                                         pPrev->mnEndPos = nHintEnd;
    2222             :                                     }
    2223             :                                 }
    2224             :                             }
    2225        8852 :                             else if( (SfxPoolItem*)-1 != pPrev->mpItem )
    2226             :                             {
    2227       14892 :                                 if( pPrev->mnEndPos == nAttrStart &&
    2228        7342 :                                     *pPrev->mpItem == *pItem )
    2229             :                                 {
    2230        7002 :                                     pPrev->mpItem = pItem;
    2231        7002 :                                     pPrev->mnEndPos = nHintEnd;
    2232             :                                 }
    2233             :                                 else
    2234             :                                 {
    2235         548 :                                     rSet.InvalidateItem( nHintWhich );
    2236         548 :                                     pPrev->mpItem = (SfxPoolItem*)-1;
    2237             :                                 }
    2238             :                             }
    2239             :                         }
    2240             : 
    2241       35070 :                         pItem = ( pItemIter.get() && !pItemIter->IsAtEnd() )
    2242       30470 :                                     ? pItemIter->NextItem() : 0;
    2243        5682 :                     } // end while
    2244             :                 }
    2245             :             }
    2246             : 
    2247       89496 :             if ( pAttrArr.get() )
    2248             :             {
    2249      160048 :                 for (size_t n = 0; n < coArrSz; ++n)
    2250             :                 {
    2251      157190 :                     const SwPoolItemEndPair& rItemPair = (*pAttrArr)[ n ];
    2252      157190 :                     if( (0 != rItemPair.mpItem) && ((SfxPoolItem*)-1 != rItemPair.mpItem) )
    2253             :                     {
    2254             :                         const sal_uInt16 nWh =
    2255        5870 :                             static_cast<sal_uInt16>(n + RES_CHRATR_BEGIN);
    2256             : 
    2257        5870 :                         if( nEnd <= rItemPair.mnEndPos ) // hinter oder genau Ende
    2258             :                         {
    2259        4256 :                             if( *rItemPair.mpItem != aFmtSet.Get( nWh ) )
    2260        4252 :                                 (*fnMergeAttr)( rSet, *rItemPair.mpItem );
    2261             :                         }
    2262             :                         else
    2263             :                             // uneindeutig
    2264        1614 :                             rSet.InvalidateItem( nWh );
    2265             :                     }
    2266             :                 }
    2267       89496 :             }
    2268             :         }
    2269      143538 :         if( aFmtSet.Count() )
    2270             :         {
    2271             :             // aus dem Format-Set alle entfernen, die im TextSet auch gesetzt sind
    2272       78628 :             aFmtSet.Differentiate( rSet );
    2273             :             // jetzt alle zusammen "mergen"
    2274       78628 :             rSet.Put( aFmtSet );
    2275      143538 :         }
    2276             :     }
    2277      190494 :     else if( !bOnlyTxtAttr )
    2278             :     {
    2279             :         // dann besorge mal die Auto-(Fmt)Attribute
    2280      185340 :         SwCntntNode::GetAttr( rSet );
    2281      185340 :         if ( bMergeIndentValuesOfNumRule )
    2282             :         {
    2283       23428 :             lcl_MergeListLevelIndentAsLRSpaceItem( *this, rSet );
    2284             :         }
    2285             :     }
    2286             : 
    2287      334032 :     return rSet.Count() != 0;
    2288             : }
    2289             : 
    2290             : namespace
    2291             : {
    2292             : 
    2293             : typedef std::pair<sal_Int32, sal_Int32> AttrSpan_t;
    2294             : typedef std::multimap<AttrSpan_t, const SwTxtAttr*> AttrSpanMap_t;
    2295             : 
    2296             : struct IsAutoStyle
    2297             : {
    2298             :     bool
    2299          94 :     operator()(const AttrSpanMap_t::value_type& i_rAttrSpan)
    2300             :     const
    2301             :     {
    2302          94 :         return i_rAttrSpan.second && i_rAttrSpan.second->Which() == RES_TXTATR_AUTOFMT;
    2303             :     }
    2304             : };
    2305             : 
    2306             : /** Removes from io_rAttrSet all items that are set by style on the
    2307             :     given span.
    2308             :   */
    2309             : struct RemovePresentAttrs
    2310             : {
    2311          94 :     RemovePresentAttrs(SfxItemSet& io_rAttrSet)
    2312          94 :         : m_rAttrSet(io_rAttrSet)
    2313             :     {
    2314          94 :     }
    2315             : 
    2316             :     void
    2317          94 :     operator()(const AttrSpanMap_t::value_type& i_rAttrSpan)
    2318             :     const
    2319             :     {
    2320          94 :         if (!i_rAttrSpan.second)
    2321             :         {
    2322         188 :             return;
    2323             :         }
    2324             : 
    2325           0 :         const SwTxtAttr* const pAutoStyle(i_rAttrSpan.second);
    2326           0 :         SfxItemIter aIter(m_rAttrSet);
    2327           0 :         const SfxPoolItem* pItem(aIter.GetCurItem());
    2328           0 :         while (pItem)
    2329             :         {
    2330           0 :             const sal_uInt16 nWhich(pItem->Which());
    2331           0 :             if (CharFmt::IsItemIncluded(nWhich, pAutoStyle))
    2332             :             {
    2333           0 :                 m_rAttrSet.ClearItem(nWhich);
    2334             :             }
    2335             : 
    2336           0 :             if (aIter.IsAtEnd())
    2337             :             {
    2338           0 :                 break;
    2339             :             }
    2340           0 :             pItem = aIter.NextItem();
    2341           0 :         }
    2342             :     }
    2343             : 
    2344             : private:
    2345             :     SfxItemSet& m_rAttrSet;
    2346             : };
    2347             : 
    2348             : /** Collects all style-covered spans from i_rHints to o_rSpanMap. In
    2349             :     addition inserts dummy spans with pointer to format equal to 0 for
    2350             :     all gaps (i.e. spans not covered by any style). This simplifies
    2351             :     creation of autostyles for all needed spans, but it means all code
    2352             :     that tries to access the pointer has to check if it's non-null!
    2353             :  */
    2354             : void
    2355         106 : lcl_CollectHintSpans(const SwpHints& i_rHints, const sal_Int32 nLength,
    2356             :         AttrSpanMap_t& o_rSpanMap)
    2357             : {
    2358         106 :     sal_Int32 nLastEnd(0);
    2359             : 
    2360         182 :     for (size_t i = 0; i < i_rHints.Count(); ++i)
    2361             :     {
    2362          76 :         const SwTxtAttr* const pHint(i_rHints[i]);
    2363          76 :         const sal_uInt16 nWhich(pHint->Which());
    2364          76 :         if (nWhich == RES_TXTATR_CHARFMT || nWhich == RES_TXTATR_AUTOFMT)
    2365             :         {
    2366           0 :             const AttrSpan_t aSpan(pHint->GetStart(), *pHint->End());
    2367           0 :             o_rSpanMap.insert(AttrSpanMap_t::value_type(aSpan, pHint));
    2368             : 
    2369             :             // < not != because there may be multiple CHARFMT at same range
    2370           0 :             if (nLastEnd < aSpan.first)
    2371             :             {
    2372             :                 // insert dummy span covering the gap
    2373             :                 o_rSpanMap.insert(AttrSpanMap_t::value_type(
    2374           0 :                     AttrSpan_t(nLastEnd, aSpan.first), (const SwTxtAttr *)0));
    2375             :             }
    2376             : 
    2377           0 :             nLastEnd = aSpan.second;
    2378             :         }
    2379             :     }
    2380             : 
    2381             :     // no hints at the end (special case: no hints at all in i_rHints)
    2382         106 :     if (nLastEnd != nLength && nLength != 0)
    2383             :     {
    2384             :         o_rSpanMap.insert(
    2385          94 :             AttrSpanMap_t::value_type(AttrSpan_t(nLastEnd, nLength), (const SwTxtAttr *)0));
    2386             :     }
    2387         106 : }
    2388             : 
    2389             : void
    2390         106 : lcl_FillWhichIds(const SfxItemSet& i_rAttrSet, std::vector<sal_uInt16>& o_rClearIds)
    2391             : {
    2392         106 :     o_rClearIds.reserve(i_rAttrSet.Count());
    2393         106 :     SfxItemIter aIter(i_rAttrSet);
    2394         106 :     const SfxPoolItem* pItem(aIter.GetCurItem());
    2395         414 :     while (pItem)
    2396             :     {
    2397         308 :         o_rClearIds.push_back(pItem->Which());
    2398             : 
    2399         308 :         if (aIter.IsAtEnd())
    2400             :         {
    2401         106 :             break;
    2402             :         }
    2403         202 :         pItem = aIter.NextItem();
    2404         106 :     }
    2405         106 : }
    2406             : 
    2407             : struct SfxItemSetClearer
    2408             : {
    2409             :     SfxItemSet & m_rItemSet;
    2410        2706 :     SfxItemSetClearer(SfxItemSet & rItemSet) : m_rItemSet(rItemSet) { }
    2411         318 :     void operator()(sal_uInt16 const nWhich) { m_rItemSet.ClearItem(nWhich); }
    2412             : };
    2413             : 
    2414             : }
    2415             : 
    2416             : /** Does the hard work of SwTxtNode::FmtToTxtAttr: the real conversion
    2417             :     of items to automatic styles.
    2418             :  */
    2419             : void
    2420      137838 : SwTxtNode::impl_FmtToTxtAttr(const SfxItemSet& i_rAttrSet)
    2421             : {
    2422             :     typedef AttrSpanMap_t::iterator AttrSpanMap_iterator_t;
    2423      137838 :     AttrSpanMap_t aAttrSpanMap;
    2424             : 
    2425      137838 :     if (i_rAttrSet.Count() == 0)
    2426             :     {
    2427      275570 :         return;
    2428             :     }
    2429             : 
    2430             :     // 1. Identify all spans in hints' array
    2431             : 
    2432         106 :     lcl_CollectHintSpans(*m_pSwpHints, m_Text.getLength(), aAttrSpanMap);
    2433             : 
    2434             :     // 2. Go through all spans and insert new attrs
    2435             : 
    2436         106 :     AttrSpanMap_iterator_t aCurRange(aAttrSpanMap.begin());
    2437         106 :     const AttrSpanMap_iterator_t aEnd(aAttrSpanMap.end());
    2438         306 :     while (aCurRange != aEnd)
    2439             :     {
    2440             :         typedef std::pair<AttrSpanMap_iterator_t, AttrSpanMap_iterator_t>
    2441             :             AttrSpanMapRange_t;
    2442          94 :         AttrSpanMapRange_t aRange(aAttrSpanMap.equal_range(aCurRange->first));
    2443             : 
    2444             :         // 2a. Collect attributes to insert
    2445             : 
    2446          94 :         SfxItemSet aCurSet(i_rAttrSet);
    2447          94 :         std::for_each(aRange.first, aRange.second, RemovePresentAttrs(aCurSet));
    2448             : 
    2449             :         // 2b. Insert automatic style containing the collected attributes
    2450             : 
    2451          94 :         if (aCurSet.Count() != 0)
    2452             :         {
    2453             :             AttrSpanMap_iterator_t aAutoStyleIt(
    2454          94 :                     std::find_if(aRange.first, aRange.second, IsAutoStyle()));
    2455          94 :             if (aAutoStyleIt != aRange.second)
    2456             :             {
    2457             :                 // there already is an automatic style on that span:
    2458             :                 // create new one and remove the original one
    2459           0 :                 SwTxtAttr* const pAutoStyle(const_cast<SwTxtAttr*>(aAutoStyleIt->second));
    2460             :                 const boost::shared_ptr<SfxItemSet> pOldStyle(
    2461             :                         static_cast<const SwFmtAutoFmt&>(
    2462           0 :                             pAutoStyle->GetAttr()).GetStyleHandle());
    2463           0 :                 aCurSet.Put(*pOldStyle);
    2464             : 
    2465             :                 // remove the old hint
    2466           0 :                 m_pSwpHints->Delete(pAutoStyle);
    2467           0 :                 DestroyAttr(pAutoStyle);
    2468             :             }
    2469             :             m_pSwpHints->Insert(
    2470          94 :                     MakeTxtAttr(*GetDoc(), aCurSet,
    2471         188 :                         aCurRange->first.first, aCurRange->first.second));
    2472             :         }
    2473             : 
    2474          94 :         aCurRange = aRange.second;
    2475          94 :     }
    2476             : 
    2477             :     // hints were directly inserted, so need to fix the Ignore flags now
    2478         106 :     m_pSwpHints->MergePortions(*this);
    2479             : 
    2480             :     // 3. Clear items from the node
    2481         212 :     std::vector<sal_uInt16> aClearedIds;
    2482         106 :     lcl_FillWhichIds(i_rAttrSet, aClearedIds);
    2483         212 :     ClearItemsFromAttrSet(aClearedIds);
    2484             : }
    2485             : 
    2486      137528 : void SwTxtNode::FmtToTxtAttr( SwTxtNode* pNd )
    2487             : {
    2488      137528 :     SfxItemSet aThisSet( GetDoc()->GetAttrPool(), aCharFmtSetRange );
    2489      137528 :     if( HasSwAttrSet() && GetpSwAttrSet()->Count() )
    2490        3468 :         aThisSet.Put( *GetpSwAttrSet() );
    2491             : 
    2492      137528 :     GetOrCreateSwpHints();
    2493             : 
    2494      137528 :     if( pNd == this )
    2495             :     {
    2496      134822 :         impl_FmtToTxtAttr(aThisSet);
    2497             :     }
    2498             :     else
    2499             :     {
    2500             :         // There are five possible combinations of items from this and
    2501             :         // pNd (pNd is the 'main' node):
    2502             : 
    2503             :         //  case    pNd     this     action
    2504             : 
    2505             :         //     1     -       -      do nothing
    2506             :         //     2     -       a      convert item to attr of this
    2507             :         //     3     a       -      convert item to attr of pNd
    2508             :         //     4     a       a      clear item in this
    2509             :         //     5     a       b      convert item to attr of this
    2510             : 
    2511        2706 :         SfxItemSet aNdSet( pNd->GetDoc()->GetAttrPool(), aCharFmtSetRange );
    2512        2706 :         if( pNd->HasSwAttrSet() && pNd->GetpSwAttrSet()->Count() )
    2513        1988 :             aNdSet.Put( *pNd->GetpSwAttrSet() );
    2514             : 
    2515        2706 :         pNd->GetOrCreateSwpHints();
    2516             : 
    2517        5412 :         std::vector<sal_uInt16> aProcessedIds;
    2518             : 
    2519        2706 :         if( aThisSet.Count() )
    2520             :         {
    2521         310 :             SfxItemIter aIter( aThisSet );
    2522         310 :             const SfxPoolItem* pItem = aIter.GetCurItem(), *pNdItem = 0;
    2523         620 :             SfxItemSet aConvertSet( GetDoc()->GetAttrPool(), aCharFmtSetRange );
    2524         620 :             std::vector<sal_uInt16> aClearWhichIds;
    2525             : 
    2526             :             while( true )
    2527             :             {
    2528         318 :                 if( SfxItemState::SET == aNdSet.GetItemState( pItem->Which(), false, &pNdItem ) )
    2529             :                 {
    2530         318 :                     if (*pItem == *pNdItem) // 4
    2531             :                     {
    2532         318 :                         aClearWhichIds.push_back( pItem->Which() );
    2533             :                     }
    2534             :                     else    // 5
    2535             :                     {
    2536           0 :                         aConvertSet.Put(*pItem);
    2537             :                     }
    2538         318 :                     aProcessedIds.push_back(pItem->Which());
    2539             :                 }
    2540             :                 else    // 2
    2541             :                 {
    2542           0 :                     aConvertSet.Put(*pItem);
    2543             :                 }
    2544             : 
    2545         318 :                 if( aIter.IsAtEnd() )
    2546         310 :                     break;
    2547           8 :                 pItem = aIter.NextItem();
    2548             :             }
    2549             : 
    2550             :             // 4/ clear items of this that are set with the same value on pNd
    2551         310 :             ClearItemsFromAttrSet( aClearWhichIds );
    2552             : 
    2553             :             // 2, 5/ convert all other items to attrs
    2554         620 :             impl_FmtToTxtAttr(aConvertSet);
    2555             :         }
    2556             : 
    2557             :         {
    2558             :             std::for_each(aProcessedIds.begin(), aProcessedIds.end(),
    2559        2706 :                     SfxItemSetClearer(aNdSet));
    2560             : 
    2561             :             // 3/ convert items to attrs
    2562        2706 :             pNd->impl_FmtToTxtAttr(aNdSet);
    2563             : 
    2564        2706 :             if( aNdSet.Count() )
    2565             :             {
    2566          18 :                 SwFmtChg aTmp1( pNd->GetFmtColl() );
    2567          18 :                 pNd->NotifyClients( &aTmp1, &aTmp1 );
    2568             :             }
    2569        2706 :         }
    2570             :     }
    2571             : 
    2572      137528 :     SetCalcHiddenCharFlags();
    2573             : 
    2574      137528 :     pNd->TryDeleteSwpHints();
    2575      137528 : }
    2576             : 
    2577       97028 : void SwpHints::CalcFlags()
    2578             : {
    2579       97028 :     m_bDDEFields = m_bFootnote = false;
    2580       97028 :     const size_t nSize = Count();
    2581      641492 :     for( size_t nPos = 0; nPos < nSize; ++nPos )
    2582             :     {
    2583      544464 :         const SwTxtAttr* pAttr = (*this)[ nPos ];
    2584      544464 :         switch( pAttr->Which() )
    2585             :         {
    2586             :         case RES_TXTATR_FTN:
    2587         502 :             m_bFootnote = true;
    2588         502 :             if ( m_bDDEFields )
    2589           0 :                 return;
    2590         502 :             break;
    2591             :         case RES_TXTATR_FIELD:
    2592             :             {
    2593      252668 :                 const SwField* pFld = pAttr->GetFmtFld().GetField();
    2594      252668 :                 if( RES_DDEFLD == pFld->GetTyp()->Which() )
    2595             :                 {
    2596           0 :                     m_bDDEFields = true;
    2597           0 :                     if ( m_bFootnote )
    2598           0 :                         return;
    2599             :                 }
    2600             :             }
    2601      252668 :             break;
    2602             :         }
    2603             :     }
    2604             : }
    2605             : 
    2606        1274 : bool SwpHints::CalcHiddenParaField()
    2607             : {
    2608        1274 :     m_bCalcHiddenParaField = false;
    2609        1274 :     bool bOldHasHiddenParaField = m_bHasHiddenParaField;
    2610        1274 :     bool bNewHasHiddenParaField  = false;
    2611        1274 :     const size_t nSize = Count();
    2612             :     const SwTxtAttr *pTxtHt;
    2613             : 
    2614        4036 :     for( size_t nPos = 0; nPos < nSize; ++nPos )
    2615             :     {
    2616        2762 :         pTxtHt = (*this)[ nPos ];
    2617        2762 :         const sal_uInt16 nWhich = pTxtHt->Which();
    2618             : 
    2619        2762 :         if( RES_TXTATR_FIELD == nWhich )
    2620             :         {
    2621        1894 :             const SwFmtFld& rFld = pTxtHt->GetFmtFld();
    2622        1894 :             if( RES_HIDDENPARAFLD == rFld.GetField()->GetTyp()->Which() )
    2623             :             {
    2624           0 :                 if( !((SwHiddenParaField*)rFld.GetField())->IsHidden() )
    2625             :                 {
    2626           0 :                     SetHiddenParaField(false);
    2627           0 :                     return bOldHasHiddenParaField != bNewHasHiddenParaField;
    2628             :                 }
    2629             :                 else
    2630             :                 {
    2631           0 :                     bNewHasHiddenParaField = true;
    2632             :                 }
    2633             :             }
    2634             :         }
    2635             :     }
    2636        1274 :     SetHiddenParaField( bNewHasHiddenParaField );
    2637        1274 :     return bOldHasHiddenParaField != bNewHasHiddenParaField;
    2638             : }
    2639             : 
    2640      341088 : void SwpHints::NoteInHistory( SwTxtAttr *pAttr, const bool bNew )
    2641             : {
    2642      341088 :     if ( m_pHistory ) { m_pHistory->AddHint( pAttr, bNew ); }
    2643      341088 : }
    2644             : 
    2645      122856 : bool SwpHints::MergePortions( SwTxtNode& rNode )
    2646             : {
    2647      122856 :     if ( !Count() )
    2648          62 :         return false;
    2649             : 
    2650             :     // sort before merging
    2651      122794 :     SwpHintsArray::Resort();
    2652             : 
    2653      122794 :     bool bRet = false;
    2654             :     typedef std::multimap< int, std::pair<SwTxtAttr*, bool> > PortionMap;
    2655      122794 :     PortionMap aPortionMap;
    2656      245588 :     std::map<int, bool> RsidOnlyAutoFmtFlagMap;
    2657      122794 :     sal_Int32 nLastPorStart = COMPLETE_STRING;
    2658      122794 :     int nKey = 0;
    2659             : 
    2660             :     // get portions by start position:
    2661      625574 :     for ( size_t i = 0; i < Count(); ++i )
    2662             :     {
    2663      502780 :         SwTxtAttr *pHt = GetTextHint( i );
    2664      948508 :         if ( RES_TXTATR_CHARFMT != pHt->Which() &&
    2665      445728 :              RES_TXTATR_AUTOFMT != pHt->Which() )
    2666             :              //&&
    2667             :              //RES_TXTATR_INETFMT != pHt->Which() )
    2668      138772 :             continue;
    2669             : 
    2670      452856 :         bool isRsidOnlyAutoFmt(false);
    2671             :         // check for RSID-only AUTOFMT
    2672      452856 :         if (RES_TXTATR_AUTOFMT == pHt->Which())
    2673             :         {
    2674             :             boost::shared_ptr<SfxItemSet> const pSet(
    2675      395804 :                     pHt->GetAutoFmt().GetStyleHandle());
    2676      395804 :             if ((pSet->Count() == 1) && pSet->GetItem(RES_CHRATR_RSID, false))
    2677             :             {
    2678             :                 // fdo#70201: eliminate no-extent RSID-only AUTOFMT
    2679             :                 // could be produced by ReplaceText or (maybe?) RstAttr
    2680         146 :                 if (pHt->GetStart() == *pHt->GetEnd())
    2681             :                 {
    2682           0 :                     SwpHintsArray::DeleteAtPos(i); // kill it without History!
    2683           0 :                     SwTxtAttr::Destroy(pHt, rNode.GetDoc()->GetAttrPool());
    2684           0 :                     --i;
    2685           0 :                     continue;
    2686             :                 }
    2687             :                 // fdo#52028: this one has _only_ RSID => ignore it completely
    2688         146 :                 if (!pHt->IsFormatIgnoreStart() || !pHt->IsFormatIgnoreEnd())
    2689             :                 {
    2690         124 :                     NoteInHistory(pHt);
    2691         124 :                     pHt->SetFormatIgnoreStart(true);
    2692         124 :                     pHt->SetFormatIgnoreEnd  (true);
    2693         124 :                     NoteInHistory(pHt, true);
    2694             :                 }
    2695         146 :                 isRsidOnlyAutoFmt = true;
    2696      395804 :             }
    2697             :         }
    2698             : 
    2699      452856 :         if (pHt->GetStart() == *pHt->GetEnd())
    2700             :         {
    2701             :             // no-length hints are a disease. ignore them here.
    2702             :             // the SwAttrIter::SeekFwd will not call Rst/Chg for them.
    2703       38924 :             continue;
    2704             :         }
    2705             : 
    2706      413932 :         const sal_Int32 nPorStart = pHt->GetStart();
    2707      413932 :         if (nPorStart != nLastPorStart)
    2708      395068 :             ++nKey;
    2709      413932 :         nLastPorStart = nPorStart;
    2710             :         aPortionMap.insert(std::make_pair(nKey,
    2711      413932 :                             std::make_pair(pHt, isRsidOnlyAutoFmt)));
    2712      413932 :         RsidOnlyAutoFmtFlagMap[nKey] = isRsidOnlyAutoFmt;
    2713             :     }
    2714             : 
    2715             :     // check if portion i can be merged with portion i+1:
    2716             :     // note: need to include i=0 to set IgnoreStart and j=nKey+1 to reset
    2717             :     // IgnoreEnd at first / last portion
    2718      122794 :     int i = 0;
    2719      122794 :     int j = i + 1;
    2720      763450 :     while ( i <= nKey )
    2721             :     {
    2722      517862 :         std::pair< PortionMap::iterator, PortionMap::iterator > aRange1 = aPortionMap.equal_range( i );
    2723      517862 :         std::pair< PortionMap::iterator, PortionMap::iterator > aRange2 = aPortionMap.equal_range( j );
    2724      517862 :         PortionMap::iterator aIter1 = aRange1.first;
    2725      517862 :         PortionMap::iterator aIter2 = aRange2.first;
    2726             : 
    2727      517862 :         enum { MATCH, DIFFER_ONLY_RSID, DIFFER } eMerge(MATCH);
    2728      517862 :         size_t const nAttributesInPor1 = std::distance(aRange1.first, aRange1.second);
    2729      517862 :         size_t const nAttributesInPor2 = std::distance(aRange2.first, aRange2.second);
    2730      517862 :         bool const isRsidOnlyAutoFmt1(RsidOnlyAutoFmtFlagMap[i]);
    2731      517862 :         bool const isRsidOnlyAutoFmt2(RsidOnlyAutoFmtFlagMap[j]);
    2732             : 
    2733             :         // if both have one they could be equal, but not if only one has it
    2734      517862 :         bool const bSkipRsidOnlyAutoFmt(nAttributesInPor1 != nAttributesInPor2);
    2735             : 
    2736             :         // this loop needs to handle the case where one has a CHARFMT and the
    2737             :         // other CHARFMT + RSID-only AUTOFMT, so...
    2738             :         // want to skip over RSID-only AUTOFMT here, hence the -1
    2739     1035724 :         if ((nAttributesInPor1 - ((isRsidOnlyAutoFmt1) ? 1 : 0)) ==
    2740      517862 :             (nAttributesInPor2 - ((isRsidOnlyAutoFmt2) ? 1 : 0))
    2741      264382 :             && (nAttributesInPor1 != 0 || nAttributesInPor2 != 0))
    2742             :         {
    2743             :             // _if_ there is one element more either in aRange1 or aRange2
    2744             :             // it _must_ be an RSID-only AUTOFMT, which can be ignored here...
    2745             :             // But if both have RSID-only AUTOFMT they could be equal, no skip!
    2746      543056 :             while (aIter1 != aRange1.second || aIter2 != aRange2.second)
    2747             :             {
    2748             :                 // first of all test if there's no gap (before skipping stuff!)
    2749      515162 :                 if (aIter1 != aRange1.second && aIter2 != aRange2.second &&
    2750      257482 :                     *aIter1->second.first->End() < aIter2->second.first->GetStart())
    2751             :                 {
    2752       20142 :                     eMerge = DIFFER;
    2753       20142 :                     break;
    2754             :                 }
    2755             :                 // skip it - cannot be equal if bSkipRsidOnlyAutoFmt is set
    2756      237538 :                 if (bSkipRsidOnlyAutoFmt
    2757      237538 :                     && aIter1 != aRange1.second && aIter1->second.second)
    2758             :                 {
    2759             :                     assert(DIFFER != eMerge);
    2760          96 :                     eMerge = DIFFER_ONLY_RSID;
    2761          96 :                     ++aIter1;
    2762          96 :                     continue;
    2763             :                 }
    2764      237442 :                 if (bSkipRsidOnlyAutoFmt
    2765      237442 :                     && aIter2 != aRange2.second && aIter2->second.second)
    2766             :                 {
    2767             :                     assert(DIFFER != eMerge);
    2768         102 :                     eMerge = DIFFER_ONLY_RSID;
    2769         102 :                     ++aIter2;
    2770         102 :                     continue;
    2771             :                 }
    2772             :                 assert(aIter1 != aRange1.second && aIter2 != aRange2.second);
    2773      237340 :                 SwTxtAttr const*const p1 = aIter1->second.first;
    2774      237340 :                 SwTxtAttr const*const p2 = aIter2->second.first;
    2775      237340 :                 if (p1->Which() != p2->Which())
    2776             :                 {
    2777        8872 :                     eMerge = DIFFER;
    2778        8872 :                     break;
    2779             :                 }
    2780      228468 :                 if (!(*p1 == *p2))
    2781             :                 {
    2782             :                     // fdo#52028: for auto styles, check if they differ only
    2783             :                     // in the RSID, which should have no effect on text layout
    2784      199484 :                     if (RES_TXTATR_AUTOFMT == p1->Which())
    2785             :                     {
    2786      190276 :                         SfxItemSet set1(*p1->GetAutoFmt().GetStyleHandle());
    2787      190278 :                         SfxItemSet set2(*p2->GetAutoFmt().GetStyleHandle());
    2788             : 
    2789      190276 :                         set1.ClearItem(RES_CHRATR_RSID);
    2790      190276 :                         set2.ClearItem(RES_CHRATR_RSID);
    2791             : 
    2792             :                         // sadly SfxItemSet::operator== does not seem to work?
    2793      190278 :                         SfxItemIter iter1(set1);
    2794      190278 :                         SfxItemIter iter2(set2);
    2795      190276 :                         if (set1.Count() == set2.Count())
    2796             :                         {
    2797       49218 :                             for (SfxPoolItem const* pItem1 = iter1.FirstItem(),
    2798       14898 :                                                   * pItem2 = iter2.FirstItem();
    2799       34318 :                                  pItem1 && pItem2;
    2800             :                                  pItem1 = iter1.NextItem(),
    2801             :                                  pItem2 = iter2.NextItem())
    2802             :                             {
    2803       53740 :                                 if (pItem1 != pItem2 ||
    2804       53740 :                                     pItem1->Which() != pItem2->Which() ||
    2805       19422 :                                     *pItem1 != *pItem2)
    2806             :                                 {
    2807       14896 :                                     eMerge = DIFFER;
    2808       14896 :                                     break;
    2809             :                                 }
    2810       19422 :                                 if (iter1.IsAtEnd())
    2811             :                                 {
    2812             :                                     assert(iter2.IsAtEnd());
    2813           0 :                                     eMerge = DIFFER_ONLY_RSID;
    2814             :                                 }
    2815             :                             }
    2816       14898 :                             if (DIFFER == eMerge)
    2817       14896 :                                 break; // outer loop too
    2818             :                         }
    2819             :                         else
    2820             :                         {
    2821      175378 :                             eMerge = DIFFER;
    2822      175378 :                             break;
    2823           2 :                         }
    2824             :                     }
    2825             :                     else
    2826             :                     {
    2827        9208 :                         eMerge = DIFFER;
    2828        9208 :                         break;
    2829             :                     }
    2830             :                 }
    2831       28986 :                 ++aIter1;
    2832       28986 :                 ++aIter2;
    2833      256936 :             }
    2834             :         }
    2835             :         else
    2836             :         {
    2837      260926 :             eMerge = DIFFER;
    2838             :         }
    2839             : 
    2840      517862 :         if (MATCH == eMerge)
    2841             :         {
    2842             :             // important: delete second range so any IgnoreStart on the first
    2843             :             // range is still valid
    2844             :             // erase all elements with key i + 1
    2845       28242 :             sal_Int32 nNewPortionEnd = 0;
    2846       56922 :             for ( aIter2 = aRange2.first; aIter2 != aRange2.second; ++aIter2 )
    2847             :             {
    2848       28680 :                 SwTxtAttr *const p2 = aIter2->second.first;
    2849       28680 :                 nNewPortionEnd = *p2->GetEnd();
    2850             : 
    2851       28680 :                 const size_t nCountBeforeDelete = Count();
    2852       28680 :                 Delete( p2 );
    2853             : 
    2854             :                 // robust: check if deletion actually took place before destroying attribute:
    2855       28680 :                 if ( Count() < nCountBeforeDelete )
    2856       28680 :                     rNode.DestroyAttr( p2 );
    2857             :             }
    2858       28242 :             aPortionMap.erase( aRange2.first, aRange2.second );
    2859       28242 :             ++j;
    2860             : 
    2861             :             // change all attributes with key i
    2862       28242 :             aRange1 = aPortionMap.equal_range( i );
    2863       56922 :             for ( aIter1 = aRange1.first; aIter1 != aRange1.second; ++aIter1 )
    2864             :             {
    2865       28680 :                 SwTxtAttr *const p1 = aIter1->second.first;
    2866       28680 :                 NoteInHistory( p1 );
    2867       28680 :                 *p1->GetEnd() = nNewPortionEnd;
    2868       28680 :                 NoteInHistory( p1, true );
    2869       28680 :                 bRet = true;
    2870             :             }
    2871             :         }
    2872             :         else
    2873             :         {
    2874             :             // when not merging the ignore flags need to be either set or reset
    2875             :             // (reset too in case one of the autofmts was recently changed)
    2876      489620 :             bool const bSetIgnoreFlag(DIFFER_ONLY_RSID == eMerge);
    2877      874872 :             for (aIter1 = aRange1.first; aIter1 != aRange1.second; ++aIter1)
    2878             :             {
    2879      385252 :                 if (!aIter1->second.second) // already set above, don't change
    2880             :                 {
    2881      385138 :                     SwTxtAttr *const pCurrent(aIter1->second.first);
    2882      385138 :                     if (pCurrent->IsFormatIgnoreEnd() != bSetIgnoreFlag)
    2883             :                     {
    2884           0 :                         NoteInHistory(pCurrent);
    2885           0 :                         pCurrent->SetFormatIgnoreEnd(bSetIgnoreFlag);
    2886           0 :                         NoteInHistory(pCurrent, true);
    2887             :                     }
    2888             :                 }
    2889             :             }
    2890      874872 :             for (aIter2 = aRange2.first; aIter2 != aRange2.second; ++aIter2)
    2891             :             {
    2892      385252 :                 if (!aIter2->second.second) // already set above, don't change
    2893             :                 {
    2894      385138 :                     SwTxtAttr *const pCurrent(aIter2->second.first);
    2895      385138 :                     if (pCurrent->IsFormatIgnoreStart() != bSetIgnoreFlag)
    2896             :                     {
    2897           0 :                         NoteInHistory(pCurrent);
    2898           0 :                         pCurrent->SetFormatIgnoreStart(bSetIgnoreFlag);
    2899           0 :                         NoteInHistory(pCurrent, true);
    2900             :                     }
    2901             :                 }
    2902             :             }
    2903      489620 :             i = j; // ++i not enough: i + 1 may have been deleted (MATCH)!
    2904      489620 :             ++j;
    2905             :         }
    2906             :     }
    2907             : 
    2908      122794 :     if ( bRet )
    2909             :     {
    2910       28212 :         SwpHintsArray::Resort();
    2911             :     }
    2912             : 
    2913      245588 :     return bRet;
    2914             : }
    2915             : 
    2916             : // check if there is already a character format and adjust the sort numbers
    2917           4 : static void lcl_CheckSortNumber( const SwpHints& rHints, SwTxtCharFmt& rNewCharFmt )
    2918             : {
    2919           4 :     const sal_Int32 nHtStart = rNewCharFmt.GetStart();
    2920           4 :     const sal_Int32 nHtEnd   = *rNewCharFmt.GetEnd();
    2921           4 :     sal_uInt16 nSortNumber = 0;
    2922             : 
    2923           4 :     for ( size_t i = 0; i < rHints.Count(); ++i )
    2924             :     {
    2925           0 :         const SwTxtAttr* pOtherHt = rHints[i];
    2926             : 
    2927           0 :         const sal_Int32 nOtherStart = pOtherHt->GetStart();
    2928             : 
    2929           0 :         if ( nOtherStart > nHtStart )
    2930           0 :             break;
    2931             : 
    2932           0 :         if ( RES_TXTATR_CHARFMT == pOtherHt->Which() )
    2933             :         {
    2934           0 :             const sal_Int32 nOtherEnd = *pOtherHt->End();
    2935             : 
    2936           0 :             if ( nOtherStart == nHtStart && nOtherEnd == nHtEnd )
    2937             :             {
    2938           0 :                 nSortNumber = static_txtattr_cast<const SwTxtCharFmt*>(pOtherHt)->GetSortNumber() + 1;
    2939             :             }
    2940             :         }
    2941             :     }
    2942             : 
    2943           4 :     if ( nSortNumber > 0 )
    2944           0 :         rNewCharFmt.SetSortNumber( nSortNumber );
    2945           4 : }
    2946             : 
    2947             : /*
    2948             :  * Try to insert the new hint.
    2949             :  * Depending on the type of the hint, this either always succeeds, or may fail.
    2950             :  * Depending on the type of the hint, other hints may be deleted or
    2951             :  * overwritten.
    2952             :  * The return value indicates successful insertion.
    2953             :  */
    2954      157694 : bool SwpHints::TryInsertHint(
    2955             :     SwTxtAttr* const pHint,
    2956             :     SwTxtNode &rNode,
    2957             :     const SetAttrMode nMode )
    2958             : {
    2959      157694 :     if ( MAX_HINTS <= Count() ) // we're sorry, this flight is overbooked...
    2960             :     {
    2961             :         OSL_FAIL("hints array full :-(");
    2962           0 :         return false;
    2963             :     }
    2964             : 
    2965             :     // Felder bilden eine Ausnahme:
    2966             :     // 1) Sie koennen nie ueberlappen
    2967             :     // 2) Wenn zwei Felder genau aneinander liegen,
    2968             :     //    sollen sie nicht zu einem verschmolzen werden.
    2969             :     // Wir koennen also auf die while-Schleife verzichten
    2970             : 
    2971      157694 :     sal_Int32 *pHtEnd = pHint->GetEnd();
    2972      157694 :     const sal_uInt16 nWhich = pHint->Which();
    2973      157694 :     std::vector<sal_uInt16> aWhichSublist;
    2974             : 
    2975      157694 :     switch( nWhich )
    2976             :     {
    2977             :     case RES_TXTATR_CHARFMT:
    2978             :     {
    2979             :         // Check if character format contains hidden attribute:
    2980       12214 :         const SwCharFmt* pFmt = pHint->GetCharFmt().GetCharFmt();
    2981             :         const SfxPoolItem* pItem;
    2982       12214 :         if ( SfxItemState::SET == pFmt->GetItemState( RES_CHRATR_HIDDEN, true, &pItem ) )
    2983           0 :             rNode.SetCalcHiddenCharFlags();
    2984             : 
    2985       12214 :         static_txtattr_cast<SwTxtCharFmt*>(pHint)->ChgTxtNode( &rNode );
    2986       12214 :         break;
    2987             :     }
    2988             :     // #i75430# Recalc hidden flags if necessary
    2989             :     case RES_TXTATR_AUTOFMT:
    2990             :     {
    2991      131600 :         boost::shared_ptr<SfxItemSet> const pSet( pHint->GetAutoFmt().GetStyleHandle() );
    2992      131600 :         if (pHint->GetStart() == *pHint->GetEnd())
    2993             :         {
    2994       50584 :             if (pSet->Count() == 1 && pSet->GetItem(RES_CHRATR_RSID, false))
    2995             :             {   // empty range RSID-only hints could cause trouble, there's no
    2996           0 :                 rNode.DestroyAttr(pHint); // need for them so don't insert
    2997           0 :                 return false;
    2998             :             }
    2999             :         }
    3000             :         // Check if auto style contains hidden attribute:
    3001      131600 :         const SfxPoolItem* pHiddenItem = CharFmt::GetItem( *pHint, RES_CHRATR_HIDDEN );
    3002      131600 :         if ( pHiddenItem )
    3003        1676 :             rNode.SetCalcHiddenCharFlags();
    3004             : 
    3005             :         // fdo#71556: populate aWhichFmtAttr member of SwMsgPoolItem
    3006      131600 :         const sal_uInt16 *pRanges = pSet->GetRanges();
    3007      657870 :         while( (*pRanges) != 0 )
    3008             :         {
    3009      394670 :             const sal_uInt16 nBeg = (*pRanges);
    3010      394670 :             ++pRanges;
    3011      394670 :             const sal_uInt16 nEnd = (*pRanges);
    3012      394670 :             ++pRanges;
    3013     6579740 :             for( sal_uInt16 nSubElem = nBeg; nSubElem <= nEnd; ++nSubElem )
    3014     6185070 :                 if( pSet->HasItem( nSubElem ) )
    3015      458852 :                     aWhichSublist.push_back( nSubElem );
    3016             :         }
    3017      131600 :         break;
    3018             :     }
    3019             :     case RES_TXTATR_INETFMT:
    3020        2842 :         static_txtattr_cast<SwTxtINetFmt*>(pHint)->InitINetFmt(rNode);
    3021        2842 :         break;
    3022             : 
    3023             :     case RES_TXTATR_FIELD:
    3024             :     case RES_TXTATR_ANNOTATION:
    3025             :     case RES_TXTATR_INPUTFIELD:
    3026             :         {
    3027        2962 :             SwTxtFld *const pTxtFld(static_txtattr_cast<SwTxtFld*>(pHint));
    3028        2962 :             bool bDelFirst = 0 != pTxtFld->GetpTxtNode();
    3029        2962 :             pTxtFld->ChgTxtNode( &rNode );
    3030        2962 :             SwDoc* pDoc = rNode.GetDoc();
    3031        2962 :             const SwField* pFld = pTxtFld->GetFmtFld().GetField();
    3032             : 
    3033        2962 :             if( !pDoc->getIDocumentFieldsAccess().IsNewFldLst() )
    3034             :             {
    3035             :                 // was fuer ein Feld ist es denn ??
    3036             :                 // bestimmte Felder mussen am Doc das Calculations-Flag updaten
    3037           4 :                 switch( pFld->GetTyp()->Which() )
    3038             :                 {
    3039             :                 case RES_DBFLD:
    3040             :                 case RES_SETEXPFLD:
    3041             :                 case RES_HIDDENPARAFLD:
    3042             :                 case RES_HIDDENTXTFLD:
    3043             :                 case RES_DBNUMSETFLD:
    3044             :                 case RES_DBNEXTSETFLD:
    3045             :                     {
    3046           0 :                         if( bDelFirst )
    3047           0 :                             pDoc->getIDocumentFieldsAccess().InsDelFldInFldLst(false, *pTxtFld);
    3048           0 :                         if( rNode.GetNodes().IsDocNodes() )
    3049           0 :                             pDoc->getIDocumentFieldsAccess().InsDelFldInFldLst(true, *pTxtFld);
    3050             :                     }
    3051           0 :                     break;
    3052             :                 case RES_DDEFLD:
    3053           0 :                     if( rNode.GetNodes().IsDocNodes() )
    3054           0 :                         ((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt();
    3055           0 :                     break;
    3056             :                 }
    3057             :             }
    3058             : 
    3059             :             // gehts ins normale Nodes-Array?
    3060        2962 :             if( rNode.GetNodes().IsDocNodes() )
    3061             :             {
    3062        2962 :                 bool bInsFldType = false;
    3063        2962 :                 switch( pFld->GetTyp()->Which() )
    3064             :                 {
    3065             :                 case RES_SETEXPFLD:
    3066         102 :                     bInsFldType = ((SwSetExpFieldType*)pFld->GetTyp())->IsDeleted();
    3067         102 :                     if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFld->GetTyp())->GetType() )
    3068             :                     {
    3069             :                         // bevor die ReferenzNummer gesetzt wird, sollte
    3070             :                         // das Feld am richtigen FeldTypen haengen!
    3071             :                         SwSetExpFieldType* pFldType = (SwSetExpFieldType*)
    3072          88 :                                     pDoc->getIDocumentFieldsAccess().InsertFldType( *pFld->GetTyp() );
    3073          88 :                         if( pFldType != pFld->GetTyp() )
    3074             :                         {
    3075           0 :                             SwFmtFld* pFmtFld = const_cast<SwFmtFld*>(&pTxtFld->GetFmtFld());
    3076           0 :                             pFmtFld->RegisterToFieldType( *pFldType );
    3077           0 :                             pFmtFld->GetField()->ChgTyp( pFldType );
    3078             :                         }
    3079          88 :                         pFldType->SetSeqRefNo( *(SwSetExpField*)pFld );
    3080             :                     }
    3081         102 :                     break;
    3082             :                 case RES_USERFLD:
    3083           4 :                     bInsFldType = ((SwUserFieldType*)pFld->GetTyp())->IsDeleted();
    3084           4 :                     break;
    3085             : 
    3086             :                 case RES_DDEFLD:
    3087           0 :                     if( pDoc->getIDocumentFieldsAccess().IsNewFldLst() )
    3088           0 :                         ((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt();
    3089           0 :                     bInsFldType = ((SwDDEFieldType*)pFld->GetTyp())->IsDeleted();
    3090           0 :                     break;
    3091             : 
    3092             :                 case RES_POSTITFLD:
    3093         194 :                     if ( pDoc->GetDocShell() )
    3094             :                     {
    3095         194 :                         pDoc->GetDocShell()->Broadcast( SwFmtFldHint(
    3096         388 :                             &pTxtFld->GetFmtFld(), SwFmtFldHintWhich::INSERTED));
    3097             :                     }
    3098         194 :                     break;
    3099             :                 }
    3100        2962 :                 if( bInsFldType )
    3101           0 :                     pDoc->getIDocumentFieldsAccess().InsDeletedFldType( *pFld->GetTyp() );
    3102             :             }
    3103             :         }
    3104        2962 :         break;
    3105             :     case RES_TXTATR_FTN :
    3106         272 :         ((SwTxtFtn*)pHint)->ChgTxtNode( &rNode );
    3107         272 :         break;
    3108             :     case RES_TXTATR_REFMARK:
    3109          82 :         static_txtattr_cast<SwTxtRefMark*>(pHint)->ChgTxtNode( &rNode );
    3110          82 :         if( rNode.GetNodes().IsDocNodes() )
    3111             :         {
    3112             :             // search for a reference with the same name
    3113             :             SwTxtAttr* pTmpHt;
    3114             :             sal_Int32 *pTmpHtEnd;
    3115             :             sal_Int32 *pTmpHintEnd;
    3116         192 :             for( size_t n = 0, nEnd = Count(); n < nEnd; ++n )
    3117             :             {
    3118         396 :                 if (RES_TXTATR_REFMARK == (pTmpHt = GetTextHint(n))->Which() &&
    3119          66 :                     pHint->GetAttr() == pTmpHt->GetAttr() &&
    3120         220 :                     0 != ( pTmpHtEnd = pTmpHt->GetEnd() ) &&
    3121           0 :                     0 != ( pTmpHintEnd = pHint->GetEnd() ) )
    3122             :                 {
    3123             :                     SwComparePosition eCmp = ::ComparePosition(
    3124           0 :                             pTmpHt->GetStart(), *pTmpHtEnd,
    3125           0 :                             pHint->GetStart(), *pTmpHintEnd );
    3126           0 :                     bool bDelOld = true, bChgStart = false, bChgEnd = false;
    3127           0 :                     switch( eCmp )
    3128             :                     {
    3129             :                     case POS_BEFORE:
    3130           0 :                     case POS_BEHIND:    bDelOld = false; break;
    3131             : 
    3132           0 :                     case POS_OUTSIDE:   bChgStart = bChgEnd = true; break;
    3133             : 
    3134             :                     case POS_COLLIDE_END:
    3135           0 :                     case POS_OVERLAP_BEFORE:    bChgStart = true; break;
    3136             :                     case POS_COLLIDE_START:
    3137           0 :                     case POS_OVERLAP_BEHIND:    bChgEnd = true; break;
    3138           0 :                     default: break;
    3139             :                     }
    3140             : 
    3141           0 :                     if( bChgStart )
    3142           0 :                         pHint->GetStart() = pTmpHt->GetStart();
    3143           0 :                     if( bChgEnd )
    3144           0 :                         *pTmpHintEnd = *pTmpHtEnd;
    3145             : 
    3146           0 :                     if( bDelOld )
    3147             :                     {
    3148           0 :                         NoteInHistory( pTmpHt );
    3149           0 :                         rNode.DestroyAttr( Cut( n-- ) );
    3150           0 :                         --nEnd;
    3151             :                     }
    3152             :                 }
    3153             :             }
    3154             :         }
    3155          82 :         break;
    3156             :     case RES_TXTATR_TOXMARK:
    3157         342 :         static_txtattr_cast<SwTxtTOXMark*>(pHint)->ChgTxtNode( &rNode );
    3158         342 :         break;
    3159             : 
    3160             :     case RES_TXTATR_CJK_RUBY:
    3161         306 :         static_txtattr_cast<SwTxtRuby*>(pHint)->InitRuby(rNode);
    3162         306 :         break;
    3163             : 
    3164             :     case RES_TXTATR_META:
    3165             :     case RES_TXTATR_METAFIELD:
    3166         194 :         static_txtattr_cast<SwTxtMeta *>(pHint)->ChgTxtNode( &rNode );
    3167         194 :         break;
    3168             : 
    3169             :     case RES_CHRATR_HIDDEN:
    3170           0 :         rNode.SetCalcHiddenCharFlags();
    3171           0 :         break;
    3172             :     }
    3173             : 
    3174      157694 :     if( nsSetAttrMode::SETATTR_DONTEXPAND & nMode )
    3175         620 :         pHint->SetDontExpand( true );
    3176             : 
    3177             :     // SwTxtAttrs ohne Ende werden sonderbehandelt:
    3178             :     // Sie werden natuerlich in das Array insertet, aber sie werden nicht
    3179             :     // in die pPrev/Next/On/Off-Verkettung aufgenommen.
    3180             :     // Der Formatierer erkennt diese TxtHints an dem CH_TXTATR_.. im Text !
    3181      157694 :     sal_Int32 nHtStart = pHint->GetStart();
    3182      157694 :     if( !pHtEnd )
    3183             :     {
    3184       10454 :         SwpHintsArray::Insert( pHint );
    3185       10454 :         CalcFlags();
    3186             : #ifdef DBG_UTIL
    3187             :         if( !rNode.GetDoc()->IsInReading() )
    3188             :             CHECK;
    3189             : #endif
    3190             :         // ... und die Abhaengigen benachrichtigen
    3191       10454 :         if(rNode.GetDepends())
    3192             :         {
    3193             :             SwUpdateAttr aHint(
    3194             :                 nHtStart,
    3195             :                 nHtStart,
    3196        3444 :                 nWhich);
    3197             : 
    3198        3444 :             rNode.ModifyNotification(0,&aHint);
    3199             :         }
    3200             : 
    3201       10454 :         return true;
    3202             :     }
    3203             : 
    3204             :     // Ab hier gibt es nur noch pHint mit einem EndIdx !!!
    3205             : 
    3206      147240 :     if( *pHtEnd < nHtStart )
    3207             :     {
    3208             :         OSL_ENSURE( *pHtEnd >= nHtStart,
    3209             :                     "+SwpHints::Insert: invalid hint, end < start" );
    3210             : 
    3211             :         // Wir drehen den Quatsch einfach um:
    3212           6 :         pHint->GetStart() = *pHtEnd;
    3213           6 :         *pHtEnd = nHtStart;
    3214           6 :         nHtStart = pHint->GetStart();
    3215             :     }
    3216             : 
    3217             :     // I need this value later on for notification but the pointer may become invalid
    3218      147240 :     const sal_Int32 nHintEnd = *pHtEnd;
    3219      147240 :     const bool bNoHintAdjustMode = (nsSetAttrMode::SETATTR_NOHINTADJUST & nMode);
    3220             : 
    3221             :     // handle nesting attributes: inserting may fail due to overlap!
    3222      147240 :     if (pHint->IsNesting())
    3223             :     {
    3224             :         const bool bRet(
    3225        3370 :             TryInsertNesting(rNode, *static_txtattr_cast<SwTxtAttrNesting*>(pHint)));
    3226        3370 :         if (!bRet) return false;
    3227             :     }
    3228             :     // Currently REFMARK and TOXMARK have OverlapAllowed set to true.
    3229             :     // These attributes may be inserted directly.
    3230             :     // Also attributes without length may be inserted directly.
    3231             :     // SETATTR_NOHINTADJUST is set e.g., during undo.
    3232             :     // Portion building in not necessary during XML import.
    3233      428672 :     else if ( !bNoHintAdjustMode &&
    3234      281808 :          !pHint->IsOverlapAllowedAttr() &&
    3235      565982 :          !rNode.GetDoc()->IsInXMLImport() &&
    3236       12202 :          ( RES_TXTATR_AUTOFMT == nWhich ||
    3237             :            RES_TXTATR_CHARFMT == nWhich ) )
    3238             :     {
    3239             :         OSL_ENSURE( nWhich != RES_TXTATR_AUTOFMT ||
    3240             :                 static_cast<const SwFmtAutoFmt&>(pHint->GetAttr()).GetStyleHandle()->GetPool() ==
    3241             :                 &rNode.GetDoc()->GetAttrPool(),
    3242             :                 "AUTOSTYLES - Pool mismatch" );
    3243             : 
    3244      140618 :         BuildPortions( rNode, *pHint, nMode );
    3245             : 
    3246      140618 :         if ( nHtStart < nHintEnd ) // skip merging for 0-length attributes
    3247       88954 :             MergePortions( rNode );
    3248             :     }
    3249             :     else
    3250             :     {
    3251             :         // There may be more than one character style at the current position.
    3252             :         // Take care of the sort number.
    3253             :         // Special case ruby portion: During import, the ruby attribute is set
    3254             :         // multiple times
    3255             :         // Special case hyperlink: During import, the ruby attribute is set
    3256             :         // multiple times
    3257             :         // FME 2007-11-08 #i82989# in NOHINTADJUST mode, we want to insert
    3258             :         // character attributes directly
    3259        3252 :         if ( ( RES_TXTATR_CHARFMT  == nWhich && !bNoHintAdjustMode ) )
    3260             :         {
    3261           8 :             BuildPortions( rNode, *pHint, nMode );
    3262             :         }
    3263             :         else
    3264             :         {
    3265             :             // #i82989# Check sort numbers in NoHintAdjustMode
    3266        3244 :             if ( RES_TXTATR_CHARFMT == nWhich )
    3267           4 :                 lcl_CheckSortNumber(*this, *static_txtattr_cast<SwTxtCharFmt*>(pHint));
    3268             : 
    3269        3244 :             SwpHintsArray::Insert( pHint );
    3270        3244 :             NoteInHistory( pHint, true );
    3271             :         }
    3272             :     }
    3273             : 
    3274             :     // ... und die Abhaengigen benachrichtigen
    3275      147236 :     if ( rNode.GetDepends() )
    3276             :     {
    3277             :         SwUpdateAttr aHint(
    3278             :             nHtStart,
    3279             :             nHtStart == nHintEnd ? nHintEnd + 1 : nHintEnd,
    3280      118388 :             nWhich);
    3281             : 
    3282      118388 :         rNode.ModifyNotification( 0, &aHint );
    3283             :     }
    3284             : 
    3285             : #ifdef DBG_UTIL
    3286             :     if( !bNoHintAdjustMode && !rNode.GetDoc()->IsInReading() )
    3287             :         CHECK;
    3288             : #endif
    3289             : 
    3290      147236 :     return true;
    3291             : }
    3292             : 
    3293       86574 : void SwpHints::DeleteAtPos( const size_t nPos )
    3294             : {
    3295       86574 :     SwTxtAttr *pHint = GetTextHint(nPos);
    3296             :     // ChainDelete( pHint );
    3297       86574 :     NoteInHistory( pHint );
    3298       86574 :     SwpHintsArray::DeleteAtPos( nPos );
    3299             : 
    3300       86574 :     if( pHint->Which() == RES_TXTATR_FIELD )
    3301             :     {
    3302         102 :         SwTxtFld *const pTxtFld(static_txtattr_cast<SwTxtFld*>(pHint));
    3303         102 :         const SwFieldType* pFldTyp = pTxtFld->GetFmtFld().GetField()->GetTyp();
    3304         102 :         if( RES_DDEFLD == pFldTyp->Which() )
    3305             :         {
    3306           0 :             const SwTxtNode* pNd = pTxtFld->GetpTxtNode();
    3307           0 :             if( pNd && pNd->GetNodes().IsDocNodes() )
    3308           0 :                 ((SwDDEFieldType*)pFldTyp)->DecRefCnt();
    3309           0 :             pTxtFld->ChgTxtNode(0);
    3310             :         }
    3311         102 :         else if ( m_bHasHiddenParaField &&
    3312           0 :                  RES_HIDDENPARAFLD == pFldTyp->Which() )
    3313             :         {
    3314           0 :             m_bCalcHiddenParaField = true;
    3315             :         }
    3316             :     }
    3317       86472 :     else if ( pHint->Which() == RES_TXTATR_ANNOTATION )
    3318             :     {
    3319          36 :         SwTxtFld *const pTxtFld(static_txtattr_cast<SwTxtFld*>(pHint));
    3320          36 :         const_cast<SwFmtFld&>(pTxtFld->GetFmtFld()).Broadcast(
    3321          72 :             SwFmtFldHint(&pTxtFld->GetFmtFld(), SwFmtFldHintWhich::REMOVED));
    3322             :     }
    3323             : 
    3324       86574 :     CalcFlags();
    3325             :     CHECK_NOTMERGED; // called from BuildPortions
    3326       86574 : }
    3327             : 
    3328             : // Ist der Hint schon bekannt, dann suche die Position und loesche ihn.
    3329             : // Ist er nicht im Array, so gibt es ein OSL_ENSURE(!!
    3330             : 
    3331       77270 : void SwpHints::Delete( SwTxtAttr* pTxtHt )
    3332             : {
    3333             :     // Attr 2.0: SwpHintsArr::Delete( pTxtHt );
    3334       77270 :     const size_t nPos = GetStartOf( pTxtHt );
    3335             :     OSL_ENSURE( SAL_MAX_SIZE != nPos, "Attribut nicht im Attribut-Array!" );
    3336       77270 :     if( SAL_MAX_SIZE != nPos )
    3337       77270 :         DeleteAtPos( nPos );
    3338       77270 : }
    3339             : 
    3340           0 : void SwTxtNode::ClearSwpHintsArr( bool bDelFields )
    3341             : {
    3342           0 :     if ( HasHints() )
    3343             :     {
    3344           0 :         size_t nPos = 0;
    3345           0 :         while ( nPos < m_pSwpHints->Count() )
    3346             :         {
    3347           0 :             SwTxtAttr* pDel = m_pSwpHints->GetTextHint( nPos );
    3348           0 :             bool bDel = false;
    3349             : 
    3350           0 :             switch( pDel->Which() )
    3351             :             {
    3352             :             case RES_TXTATR_FLYCNT:
    3353             :             case RES_TXTATR_FTN:
    3354           0 :                 break;
    3355             : 
    3356             :             case RES_TXTATR_FIELD:
    3357             :             case RES_TXTATR_ANNOTATION:
    3358             :             case RES_TXTATR_INPUTFIELD:
    3359           0 :                 if( bDelFields )
    3360           0 :                     bDel = true;
    3361           0 :                 break;
    3362             :             default:
    3363           0 :                 bDel = true; break;
    3364             :             }
    3365             : 
    3366           0 :             if( bDel )
    3367             :             {
    3368           0 :                 m_pSwpHints->SwpHintsArray::DeleteAtPos( nPos );
    3369           0 :                 DestroyAttr( pDel );
    3370             :             }
    3371             :             else
    3372           0 :                 ++nPos;
    3373             :         }
    3374             :     }
    3375           0 : }
    3376             : 
    3377      294860 : sal_uInt16 SwTxtNode::GetLang( const sal_Int32 nBegin, const sal_Int32 nLen,
    3378             :                            sal_uInt16 nScript ) const
    3379             : {
    3380      294860 :     sal_uInt16 nRet = LANGUAGE_DONTKNOW;
    3381             : 
    3382      294860 :     if ( ! nScript )
    3383             :     {
    3384      270787 :         nScript = g_pBreakIt->GetRealScriptOfText( m_Text, nBegin );
    3385             :     }
    3386             : 
    3387             :     // #i91465# Consider nScript if pSwpHints == 0
    3388      294860 :     const sal_uInt16 nWhichId = GetWhichOfScript( RES_CHRATR_LANGUAGE, nScript );
    3389             : 
    3390      294860 :     if ( HasHints() )
    3391             :     {
    3392       46610 :         const sal_Int32 nEnd = nBegin + nLen;
    3393       46610 :         const size_t nSize = m_pSwpHints->Count();
    3394      139400 :         for ( size_t i = 0; i < nSize; ++i )
    3395             :         {
    3396             :             // ist der Attribut-Anfang schon groesser als der Idx ?
    3397       95903 :             const SwTxtAttr *pHt = m_pSwpHints->operator[](i);
    3398       95903 :             const sal_Int32 nAttrStart = pHt->GetStart();
    3399       95903 :             if( nEnd < nAttrStart )
    3400        3113 :                 break;
    3401             : 
    3402       92790 :             const sal_uInt16 nWhich = pHt->Which();
    3403             : 
    3404      196630 :             if( nWhichId == nWhich ||
    3405      173224 :                     ( ( pHt->IsCharFmtAttr() || RES_TXTATR_AUTOFMT == nWhich ) && CharFmt::IsItemIncluded( nWhichId, pHt ) ) )
    3406             :             {
    3407       11050 :                 const sal_Int32 *pEndIdx = pHt->End();
    3408             :                 // Ueberlappt das Attribut den Bereich?
    3409             : 
    3410       11050 :                 if (!pEndIdx)
    3411           0 :                     continue;
    3412             : 
    3413       21900 :                 if( nLen ? ( nAttrStart < nEnd && nBegin < *pEndIdx )
    3414        8314 :                          : (( nAttrStart < nBegin &&
    3415        8932 :                                 ( pHt->DontExpand() ? nBegin < *pEndIdx
    3416       40130 :                                                     : nBegin <= *pEndIdx )) ||
    3417        2536 :                             ( nBegin == nAttrStart &&
    3418        2712 :                                 ( nAttrStart == *pEndIdx || !nBegin ))) )
    3419             :                 {
    3420        7160 :                     const SfxPoolItem* pItem = CharFmt::GetItem( *pHt, nWhichId );
    3421        7160 :                     const sal_uInt16 nLng = ((SvxLanguageItem*)pItem)->GetLanguage();
    3422             : 
    3423             :                     // Umfasst das Attribut den Bereich komplett?
    3424        7160 :                     if( nAttrStart <= nBegin && nEnd <= *pEndIdx )
    3425        7160 :                         nRet = nLng;
    3426           0 :                     else if( LANGUAGE_DONTKNOW == nRet )
    3427           0 :                         nRet = nLng; // partielle Ueberlappung, der 1. gewinnt
    3428             :                 }
    3429             :             }
    3430             :         }
    3431             :     }
    3432      294860 :     if( LANGUAGE_DONTKNOW == nRet )
    3433             :     {
    3434      289974 :         nRet = ((SvxLanguageItem&)GetSwAttrSet().Get( nWhichId )).GetLanguage();
    3435      289974 :         if( LANGUAGE_DONTKNOW == nRet )
    3436        2222 :             nRet = static_cast<sal_uInt16>(GetAppLanguage());
    3437             :     }
    3438      294860 :     return nRet;
    3439             : }
    3440             : 
    3441        9466 : sal_Unicode GetCharOfTxtAttr( const SwTxtAttr& rAttr )
    3442             : {
    3443        9466 :     sal_Unicode cRet = CH_TXTATR_BREAKWORD;
    3444        9466 :     switch ( rAttr.Which() )
    3445             :     {
    3446             :         case RES_TXTATR_REFMARK:
    3447             :         case RES_TXTATR_TOXMARK:
    3448         368 :             cRet = CH_TXTATR_INWORD;
    3449         368 :         break;
    3450             : 
    3451             :         case RES_TXTATR_FIELD:
    3452             :         case RES_TXTATR_FLYCNT:
    3453             :         case RES_TXTATR_FTN:
    3454             :         case RES_TXTATR_META:
    3455             :         case RES_TXTATR_METAFIELD:
    3456             :         case RES_TXTATR_ANNOTATION:
    3457             :         {
    3458        9098 :             cRet = CH_TXTATR_BREAKWORD;
    3459             :         }
    3460        9098 :         break;
    3461             : 
    3462             :         default:
    3463             :             OSL_FAIL("GetCharOfTxtAttr: unknown attr");
    3464           0 :             break;
    3465             :     }
    3466        9466 :     return cRet;
    3467         270 : }
    3468             : 
    3469             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10