LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/editeng/source/editeng - editdoc.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1096 1421 77.1 %
Date: 2013-07-09 Functions: 165 201 82.1 %
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 <comphelper/string.hxx>
      21             : #include <vcl/wrkwin.hxx>
      22             : #include <vcl/dialog.hxx>
      23             : #include <vcl/msgbox.hxx>
      24             : #include <vcl/svapp.hxx>
      25             : 
      26             : #include <editeng/tstpitem.hxx>
      27             : #include <editeng/colritem.hxx>
      28             : #include <editeng/fontitem.hxx>
      29             : #include <editeng/crossedoutitem.hxx>
      30             : #include <editeng/fhgtitem.hxx>
      31             : #include <editeng/postitem.hxx>
      32             : #include <editeng/kernitem.hxx>
      33             : #include <editeng/wrlmitem.hxx>
      34             : #include <editeng/wghtitem.hxx>
      35             : #include <editeng/udlnitem.hxx>
      36             : #include <editeng/contouritem.hxx>
      37             : #include <editeng/escapementitem.hxx>
      38             : #include <editeng/shdditem.hxx>
      39             : #include <editeng/autokernitem.hxx>
      40             : #include <editeng/charsetcoloritem.hxx>
      41             : #include <editeng/langitem.hxx>
      42             : #include <editeng/emphasismarkitem.hxx>
      43             : #include <editeng/charscaleitem.hxx>
      44             : #include <editeng/charreliefitem.hxx>
      45             : #include <editeng/xmlcnitm.hxx>
      46             : #include <editeng/editids.hrc>
      47             : #include "editeng/editdata.hxx"
      48             : #include "editeng/lrspitem.hxx"
      49             : #include "editeng/ulspitem.hxx"
      50             : #include "editeng/lspcitem.hxx"
      51             : 
      52             : #include <editdoc.hxx>
      53             : #include <editdbg.hxx>
      54             : #include <editeng/eerdll.hxx>
      55             : #include <eerdll2.hxx>
      56             : 
      57             : #include <tools/stream.hxx>
      58             : #include <tools/debug.hxx>
      59             : #include <tools/shl.hxx>
      60             : #include <com/sun/star/i18n/ScriptType.hpp>
      61             : 
      62             : #include <cassert>
      63             : #include <limits>
      64             : 
      65             : #include <boost/bind.hpp>
      66             : 
      67             : using namespace ::com::sun::star;
      68             : 
      69             : 
      70             : // ------------------------------------------------------------
      71             : 
      72     5243095 : sal_uInt16 GetScriptItemId( sal_uInt16 nItemId, short nScriptType )
      73             : {
      74     5243095 :     sal_uInt16 nId = nItemId;
      75             : 
      76     5243095 :     if ( ( nScriptType == i18n::ScriptType::ASIAN ) ||
      77             :          ( nScriptType == i18n::ScriptType::COMPLEX ) )
      78             :     {
      79          46 :         switch ( nItemId )
      80             :         {
      81             :             case EE_CHAR_LANGUAGE:
      82          14 :                 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_LANGUAGE_CJK : EE_CHAR_LANGUAGE_CTL;
      83          14 :             break;
      84             :             case EE_CHAR_FONTINFO:
      85           8 :                 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK : EE_CHAR_FONTINFO_CTL;
      86           8 :             break;
      87             :             case EE_CHAR_FONTHEIGHT:
      88           8 :                 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTHEIGHT_CJK : EE_CHAR_FONTHEIGHT_CTL;
      89           8 :             break;
      90             :             case EE_CHAR_WEIGHT:
      91           8 :                 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_WEIGHT_CJK : EE_CHAR_WEIGHT_CTL;
      92           8 :             break;
      93             :             case EE_CHAR_ITALIC:
      94           8 :                 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL;
      95           8 :             break;
      96             :         }
      97             :     }
      98             : 
      99     5243095 :     return nId;
     100             : }
     101             : 
     102     2189821 : sal_Bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType )
     103             : {
     104     2189821 :     sal_Bool bValid = sal_True;
     105             : 
     106     2189821 :     switch ( nItemId )
     107             :     {
     108             :         case EE_CHAR_LANGUAGE:
     109      179187 :             bValid = nScriptType == i18n::ScriptType::LATIN;
     110      179187 :         break;
     111             :         case EE_CHAR_LANGUAGE_CJK:
     112      177781 :             bValid = nScriptType == i18n::ScriptType::ASIAN;
     113      177781 :         break;
     114             :         case EE_CHAR_LANGUAGE_CTL:
     115        6420 :             bValid = nScriptType == i18n::ScriptType::COMPLEX;
     116        6420 :         break;
     117             :         case EE_CHAR_FONTINFO:
     118      180668 :             bValid = nScriptType == i18n::ScriptType::LATIN;
     119      180668 :         break;
     120             :         case EE_CHAR_FONTINFO_CJK:
     121      178851 :             bValid = nScriptType == i18n::ScriptType::ASIAN;
     122      178851 :         break;
     123             :         case EE_CHAR_FONTINFO_CTL:
     124      179044 :             bValid = nScriptType == i18n::ScriptType::COMPLEX;
     125      179044 :         break;
     126             :         case EE_CHAR_FONTHEIGHT:
     127      180663 :             bValid = nScriptType == i18n::ScriptType::LATIN;
     128      180663 :         break;
     129             :         case EE_CHAR_FONTHEIGHT_CJK:
     130      178534 :             bValid = nScriptType == i18n::ScriptType::ASIAN;
     131      178534 :         break;
     132             :         case EE_CHAR_FONTHEIGHT_CTL:
     133      177559 :             bValid = nScriptType == i18n::ScriptType::COMPLEX;
     134      177559 :         break;
     135             :         case EE_CHAR_WEIGHT:
     136      145407 :             bValid = nScriptType == i18n::ScriptType::LATIN;
     137      145407 :         break;
     138             :         case EE_CHAR_WEIGHT_CJK:
     139      143297 :             bValid = nScriptType == i18n::ScriptType::ASIAN;
     140      143297 :         break;
     141             :         case EE_CHAR_WEIGHT_CTL:
     142      143201 :             bValid = nScriptType == i18n::ScriptType::COMPLEX;
     143      143201 :         break;
     144             :         case EE_CHAR_ITALIC:
     145        8801 :             bValid = nScriptType == i18n::ScriptType::LATIN;
     146        8801 :         break;
     147             :         case EE_CHAR_ITALIC_CJK:
     148        6775 :             bValid = nScriptType == i18n::ScriptType::ASIAN;
     149        6775 :         break;
     150             :         case EE_CHAR_ITALIC_CTL:
     151        7174 :             bValid = nScriptType == i18n::ScriptType::COMPLEX;
     152        7174 :         break;
     153             :     }
     154             : 
     155     2189821 :     return bValid;
     156             : }
     157             : 
     158             : 
     159             : // ------------------------------------------------------------
     160             : 
     161             : // Should later be moved to TOOLS/STRING (Current: 303)
     162             : // for Grep: WS_TARGET
     163             : 
     164             : DBG_NAME( EE_TextPortion );
     165             : DBG_NAME( EE_EditLine );
     166             : DBG_NAME( EE_ContentNode );
     167             : DBG_NAME( EE_CharAttribList );
     168             : DBG_NAME( EE_ParaPortion )
     169             : 
     170             : const SfxItemInfo aItemInfos[EDITITEMCOUNT] = {
     171             :         { SID_ATTR_FRAMEDIRECTION, SFX_ITEM_POOLABLE },         // EE_PARA_WRITINGDIR
     172             :         { 0, SFX_ITEM_POOLABLE },                               // EE_PARA_XMLATTRIBS
     173             :         { SID_ATTR_PARA_HANGPUNCTUATION, SFX_ITEM_POOLABLE },   // EE_PARA_HANGINGPUNCTUATION
     174             :         { SID_ATTR_PARA_FORBIDDEN_RULES, SFX_ITEM_POOLABLE },
     175             :         { SID_ATTR_PARA_SCRIPTSPACE, SFX_ITEM_POOLABLE },       // EE_PARA_ASIANCJKSPACING
     176             :         { SID_ATTR_NUMBERING_RULE, SFX_ITEM_POOLABLE },         // EE_PARA_NUMBULL
     177             :         { 0, SFX_ITEM_POOLABLE },                               // EE_PARA_HYPHENATE
     178             :         { 0, SFX_ITEM_POOLABLE },                               // EE_PARA_BULLETSTATE
     179             :         { 0, SFX_ITEM_POOLABLE },                               // EE_PARA_OUTLLRSPACE
     180             :         { SID_ATTR_PARA_OUTLLEVEL, SFX_ITEM_POOLABLE },         // EE_PARA_OUTLLEVEL
     181             :         { SID_ATTR_PARA_BULLET, SFX_ITEM_POOLABLE },            // EE_PARA_BULLET
     182             :         { SID_ATTR_LRSPACE, SFX_ITEM_POOLABLE },                // EE_PARA_LRSPACE
     183             :         { SID_ATTR_ULSPACE, SFX_ITEM_POOLABLE },                // EE_PARA_ULSPACE
     184             :         { SID_ATTR_PARA_LINESPACE, SFX_ITEM_POOLABLE },         // EE_PARA_SBL
     185             :         { SID_ATTR_PARA_ADJUST, SFX_ITEM_POOLABLE },            // EE_PARA_JUST
     186             :         { SID_ATTR_TABSTOP, SFX_ITEM_POOLABLE },                // EE_PARA_TABS
     187             :         { SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD, SFX_ITEM_POOLABLE }, // EE_PARA_JUST_METHOD
     188             :         { SID_ATTR_ALIGN_VER_JUSTIFY, SFX_ITEM_POOLABLE },      // EE_PARA_VER_JUST
     189             :         { SID_ATTR_CHAR_COLOR, SFX_ITEM_POOLABLE },
     190             :         { SID_ATTR_CHAR_FONT, SFX_ITEM_POOLABLE },
     191             :         { SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEM_POOLABLE },
     192             :         { SID_ATTR_CHAR_SCALEWIDTH, SFX_ITEM_POOLABLE },
     193             :         { SID_ATTR_CHAR_WEIGHT, SFX_ITEM_POOLABLE },
     194             :         { SID_ATTR_CHAR_UNDERLINE, SFX_ITEM_POOLABLE },
     195             :         { SID_ATTR_CHAR_STRIKEOUT, SFX_ITEM_POOLABLE },
     196             :         { SID_ATTR_CHAR_POSTURE, SFX_ITEM_POOLABLE },
     197             :         { SID_ATTR_CHAR_CONTOUR, SFX_ITEM_POOLABLE },
     198             :         { SID_ATTR_CHAR_SHADOWED, SFX_ITEM_POOLABLE },
     199             :         { SID_ATTR_CHAR_ESCAPEMENT, SFX_ITEM_POOLABLE },
     200             :         { SID_ATTR_CHAR_AUTOKERN, SFX_ITEM_POOLABLE },
     201             :         { SID_ATTR_CHAR_KERNING, SFX_ITEM_POOLABLE },
     202             :         { SID_ATTR_CHAR_WORDLINEMODE, SFX_ITEM_POOLABLE },
     203             :         { SID_ATTR_CHAR_LANGUAGE, SFX_ITEM_POOLABLE },
     204             :         { SID_ATTR_CHAR_CJK_LANGUAGE, SFX_ITEM_POOLABLE },
     205             :         { SID_ATTR_CHAR_CTL_LANGUAGE, SFX_ITEM_POOLABLE },
     206             :         { SID_ATTR_CHAR_CJK_FONT, SFX_ITEM_POOLABLE },
     207             :         { SID_ATTR_CHAR_CTL_FONT, SFX_ITEM_POOLABLE },
     208             :         { SID_ATTR_CHAR_CJK_FONTHEIGHT, SFX_ITEM_POOLABLE },
     209             :         { SID_ATTR_CHAR_CTL_FONTHEIGHT, SFX_ITEM_POOLABLE },
     210             :         { SID_ATTR_CHAR_CJK_WEIGHT, SFX_ITEM_POOLABLE },
     211             :         { SID_ATTR_CHAR_CTL_WEIGHT, SFX_ITEM_POOLABLE },
     212             :         { SID_ATTR_CHAR_CJK_POSTURE, SFX_ITEM_POOLABLE },
     213             :         { SID_ATTR_CHAR_CTL_POSTURE, SFX_ITEM_POOLABLE },
     214             :         { SID_ATTR_CHAR_EMPHASISMARK, SFX_ITEM_POOLABLE },
     215             :         { SID_ATTR_CHAR_RELIEF, SFX_ITEM_POOLABLE },
     216             :         { 0, SFX_ITEM_POOLABLE },                           // EE_CHAR_RUBI_DUMMY
     217             :         { 0, SFX_ITEM_POOLABLE },                           // EE_CHAR_XMLATTRIBS
     218             :         { SID_ATTR_CHAR_OVERLINE, SFX_ITEM_POOLABLE },
     219             :         { 0, SFX_ITEM_POOLABLE },                           // EE_FEATURE_TAB
     220             :         { 0, SFX_ITEM_POOLABLE },                           // EE_FEATURE_LINEBR
     221             :         { SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEM_POOLABLE },  // EE_FEATURE_NOTCONV
     222             :         { SID_FIELD, SFX_ITEM_POOLABLE }
     223             : };
     224             : 
     225             : const sal_uInt16 aV1Map[] = {
     226             :     3999, 4001, 4002, 4003, 4004, 4005, 4006,
     227             :     4007, 4008, 4009, 4010, 4011, 4012, 4013, 4017, 4018, 4019 // MI: 4019?
     228             : };
     229             : 
     230             : const sal_uInt16 aV2Map[] = {
     231             :     3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009,
     232             :     4010, 4011, 4012, 4013, 4014, 4015, 4016, 4018, 4019, 4020
     233             : };
     234             : 
     235             : const sal_uInt16 aV3Map[] = {
     236             :     3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007,
     237             :     4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019,
     238             :     4020, 4021
     239             : };
     240             : 
     241             : const sal_uInt16 aV4Map[] = {
     242             :     3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003,
     243             :     4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013,
     244             :     4014, 4015, 4016, 4017, 4018,
     245             :     /* CJK Items inserted here: EE_CHAR_LANGUAGE - EE_CHAR_XMLATTRIBS */
     246             :     4034, 4035, 4036, 4037
     247             : };
     248             : 
     249             : const sal_uInt16 aV5Map[] = {
     250             :     3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003,
     251             :     4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013,
     252             :     4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023,
     253             :     4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033,
     254             :     /* EE_CHAR_OVERLINE inserted here */
     255             :     4035, 4036, 4037, 4038
     256             : };
     257             : 
     258     1103739 : EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_uInt16 nS, sal_uInt16 nE )
     259             : {
     260             :     // Create a new attribute in the pool
     261     1103739 :     const SfxPoolItem& rNew = rPool.Put( rAttr );
     262             : 
     263     1103739 :     EditCharAttrib* pNew = 0;
     264     1103739 :     switch( rNew.Which() )
     265             :     {
     266             :         case EE_CHAR_LANGUAGE:
     267             :         case EE_CHAR_LANGUAGE_CJK:
     268             :         case EE_CHAR_LANGUAGE_CTL:
     269             :         {
     270      187958 :             pNew = new EditCharAttribLanguage( (const SvxLanguageItem&)rNew, nS, nE );
     271             :         }
     272      187958 :         break;
     273             :         case EE_CHAR_COLOR:
     274             :         {
     275       94298 :             pNew = new EditCharAttribColor( (const SvxColorItem&)rNew, nS, nE );
     276             :         }
     277       94298 :         break;
     278             :         case EE_CHAR_FONTINFO:
     279             :         case EE_CHAR_FONTINFO_CJK:
     280             :         case EE_CHAR_FONTINFO_CTL:
     281             :         {
     282      281369 :             pNew = new EditCharAttribFont( (const SvxFontItem&)rNew, nS, nE );
     283             :         }
     284      281369 :         break;
     285             :         case EE_CHAR_FONTHEIGHT:
     286             :         case EE_CHAR_FONTHEIGHT_CJK:
     287             :         case EE_CHAR_FONTHEIGHT_CTL:
     288             :         {
     289      280405 :             pNew = new EditCharAttribFontHeight( (const SvxFontHeightItem&)rNew, nS, nE );
     290             :         }
     291      280405 :         break;
     292             :         case EE_CHAR_FONTWIDTH:
     293             :         {
     294        1357 :             pNew = new EditCharAttribFontWidth( (const SvxCharScaleWidthItem&)rNew, nS, nE );
     295             :         }
     296        1357 :         break;
     297             :         case EE_CHAR_WEIGHT:
     298             :         case EE_CHAR_WEIGHT_CJK:
     299             :         case EE_CHAR_WEIGHT_CTL:
     300             :         {
     301      222654 :             pNew = new EditCharAttribWeight( (const SvxWeightItem&)rNew, nS, nE );
     302             :         }
     303      222654 :         break;
     304             :         case EE_CHAR_UNDERLINE:
     305             :         {
     306        2238 :             pNew = new EditCharAttribUnderline( (const SvxUnderlineItem&)rNew, nS, nE );
     307             :         }
     308        2238 :         break;
     309             :         case EE_CHAR_OVERLINE:
     310             :         {
     311         950 :             pNew = new EditCharAttribOverline( (const SvxOverlineItem&)rNew, nS, nE );
     312             :         }
     313         950 :         break;
     314             :         case EE_CHAR_EMPHASISMARK:
     315             :         {
     316        1424 :             pNew = new EditCharAttribEmphasisMark( (const SvxEmphasisMarkItem&)rNew, nS, nE );
     317             :         }
     318        1424 :         break;
     319             :         case EE_CHAR_RELIEF:
     320             :         {
     321        1406 :             pNew = new EditCharAttribRelief( (const SvxCharReliefItem&)rNew, nS, nE );
     322             :         }
     323        1406 :         break;
     324             :         case EE_CHAR_STRIKEOUT:
     325             :         {
     326        2124 :             pNew = new EditCharAttribStrikeout( (const SvxCrossedOutItem&)rNew, nS, nE );
     327             :         }
     328        2124 :         break;
     329             :         case EE_CHAR_ITALIC:
     330             :         case EE_CHAR_ITALIC_CJK:
     331             :         case EE_CHAR_ITALIC_CTL:
     332             :         {
     333        5475 :             pNew = new EditCharAttribItalic( (const SvxPostureItem&)rNew, nS, nE );
     334             :         }
     335        5475 :         break;
     336             :         case EE_CHAR_OUTLINE:
     337             :         {
     338        1641 :             pNew = new EditCharAttribOutline( (const SvxContourItem&)rNew, nS, nE );
     339             :         }
     340        1641 :         break;
     341             :         case EE_CHAR_SHADOW:
     342             :         {
     343        1679 :             pNew = new EditCharAttribShadow( (const SvxShadowedItem&)rNew, nS, nE );
     344             :         }
     345        1679 :         break;
     346             :         case EE_CHAR_ESCAPEMENT:
     347             :         {
     348        6071 :             pNew = new EditCharAttribEscapement( (const SvxEscapementItem&)rNew, nS, nE );
     349             :         }
     350        6071 :         break;
     351             :         case EE_CHAR_PAIRKERNING:
     352             :         {
     353        1539 :             pNew = new EditCharAttribPairKerning( (const SvxAutoKernItem&)rNew, nS, nE );
     354             :         }
     355        1539 :         break;
     356             :         case EE_CHAR_KERNING:
     357             :         {
     358        1801 :             pNew = new EditCharAttribKerning( (const SvxKerningItem&)rNew, nS, nE );
     359             :         }
     360        1801 :         break;
     361             :         case EE_CHAR_WLM:
     362             :         {
     363        1504 :             pNew = new EditCharAttribWordLineMode( (const SvxWordLineModeItem&)rNew, nS, nE );
     364             :         }
     365        1504 :         break;
     366             :         case EE_CHAR_XMLATTRIBS:
     367             :         {
     368        1282 :             pNew = new EditCharAttrib( rNew, nS, nE );  // Attribute is only for holding XML information...
     369             :         }
     370        1282 :         break;
     371             :         case EE_FEATURE_TAB:
     372             :         {
     373          94 :             pNew = new EditCharAttribTab( (const SfxVoidItem&)rNew, nS );
     374             :         }
     375          94 :         break;
     376             :         case EE_FEATURE_LINEBR:
     377             :         {
     378          29 :             pNew = new EditCharAttribLineBreak( (const SfxVoidItem&)rNew, nS );
     379             :         }
     380          29 :         break;
     381             :         case EE_FEATURE_FIELD:
     382             :         {
     383        6441 :             pNew = new EditCharAttribField( (const SvxFieldItem&)rNew, nS );
     384             :         }
     385        6441 :         break;
     386             :         default:
     387             :         {
     388             :             OSL_FAIL( "Invalid Attribute!" );
     389             :         }
     390             :     }
     391     1103739 :     return pNew;
     392             : }
     393             : 
     394      466395 : TextPortionList::TextPortionList()
     395             : {
     396      466395 : }
     397             : 
     398      932672 : TextPortionList::~TextPortionList()
     399             : {
     400      466336 :     Reset();
     401      466336 : }
     402             : 
     403      506553 : void TextPortionList::Reset()
     404             : {
     405      506553 :     maPortions.clear();
     406      506553 : }
     407             : 
     408      138522 : void TextPortionList::DeleteFromPortion(size_t nDelFrom)
     409             : {
     410             :     DBG_ASSERT( ( nDelFrom < maPortions.size() ) || ( (nDelFrom == 0) && maPortions.empty() ), "DeleteFromPortion: Out of range" );
     411      138522 :     PortionsType::iterator it = maPortions.begin();
     412      138522 :     std::advance(it, nDelFrom);
     413      138522 :     maPortions.erase(it, maPortions.end());
     414      138522 : }
     415             : 
     416     1465289 : size_t TextPortionList::Count() const
     417             : {
     418     1465289 :     return maPortions.size();
     419             : }
     420             : 
     421       26600 : const TextPortion* TextPortionList::operator[](size_t nPos) const
     422             : {
     423       26600 :     return &maPortions[nPos];
     424             : }
     425             : 
     426     1319312 : TextPortion* TextPortionList::operator[](size_t nPos)
     427             : {
     428     1319312 :     return &maPortions[nPos];
     429             : }
     430             : 
     431      456399 : void TextPortionList::Append(TextPortion* p)
     432             : {
     433      456399 :     maPortions.push_back(p);
     434      456399 : }
     435             : 
     436       46645 : void TextPortionList::Insert(size_t nPos, TextPortion* p)
     437             : {
     438       46645 :     maPortions.insert(maPortions.begin()+nPos, p);
     439       46645 : }
     440             : 
     441           0 : void TextPortionList::Remove(size_t nPos)
     442             : {
     443           0 :     maPortions.erase(maPortions.begin()+nPos);
     444           0 : }
     445             : 
     446             : namespace {
     447             : 
     448             : class FindTextPortionByAddress : std::unary_function<TextPortion, bool>
     449             : {
     450             :     const TextPortion* mp;
     451             : public:
     452           0 :     FindTextPortionByAddress(const TextPortion* p) : mp(p) {}
     453           0 :     bool operator() (const TextPortion& v) const
     454             :     {
     455           0 :         return &v == mp;
     456             :     }
     457             : };
     458             : 
     459             : }
     460             : 
     461           0 : size_t TextPortionList::GetPos(const TextPortion* p) const
     462             : {
     463             :     PortionsType::const_iterator it =
     464           0 :         std::find_if(maPortions.begin(), maPortions.end(), FindTextPortionByAddress(p));
     465             : 
     466           0 :     if (it == maPortions.end())
     467           0 :         return std::numeric_limits<size_t>::max(); // not found.
     468             : 
     469           0 :     return std::distance(maPortions.begin(), it);
     470             : }
     471             : 
     472         958 : size_t TextPortionList::FindPortion(
     473             :     sal_uInt16 nCharPos, sal_uInt16& nPortionStart, bool bPreferStartingPortion) const
     474             : {
     475             :     // When nCharPos at portion limit, the left portion is found
     476         958 :     sal_uInt16 nTmpPos = 0;
     477         958 :     size_t n = maPortions.size();
     478         994 :     for (size_t i = 0; i < n; ++i)
     479             :     {
     480         994 :         const TextPortion& rPortion = maPortions[i];
     481         994 :         nTmpPos = nTmpPos + rPortion.GetLen();
     482         994 :         if ( nTmpPos >= nCharPos )
     483             :         {
     484             :             // take this one if we don't prefer the starting portion, or if it's the last one
     485         958 :             if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( i == n-1 ) )
     486             :             {
     487         958 :                 nPortionStart = nTmpPos - rPortion.GetLen();
     488         958 :                 return i;
     489             :             }
     490             :         }
     491             :     }
     492             :     OSL_FAIL( "FindPortion: Not found!" );
     493           0 :     return n - 1;
     494             : }
     495             : 
     496           0 : sal_uInt16 TextPortionList::GetStartPos(size_t nPortion)
     497             : {
     498           0 :     sal_uInt16 nPos = 0;
     499           0 :     for (size_t i = 0; i < nPortion; ++i)
     500             :     {
     501           0 :         const TextPortion& rPortion = maPortions[i];
     502           0 :         nPos = nPos + rPortion.GetLen();
     503             :     }
     504           0 :     return nPos;
     505             : }
     506             : 
     507             : 
     508           0 : ExtraPortionInfo::ExtraPortionInfo()
     509             : {
     510           0 :     nOrgWidth = 0;
     511           0 :     nWidthFullCompression = 0;
     512           0 :     nMaxCompression100thPercent = 0;
     513           0 :     nAsianCompressionTypes = 0;
     514           0 :     nPortionOffsetX = 0;
     515           0 :     bFirstCharIsRightPunktuation = sal_False;
     516           0 :     bCompressed = sal_False;
     517           0 :     pOrgDXArray = NULL;
     518           0 : }
     519             : 
     520           0 : ExtraPortionInfo::~ExtraPortionInfo()
     521             : {
     522           0 :     delete[] pOrgDXArray;
     523           0 : }
     524             : 
     525           0 : void ExtraPortionInfo::SaveOrgDXArray( const sal_Int32* pDXArray, sal_uInt16 nLen )
     526             : {
     527           0 :     delete[] pOrgDXArray;
     528           0 :     pOrgDXArray = new sal_Int32[nLen];
     529           0 :     memcpy( pOrgDXArray, pDXArray, nLen*sizeof(sal_Int32) );
     530           0 : }
     531             : 
     532             : 
     533      466395 : ParaPortion::ParaPortion( ContentNode* pN )
     534             : {
     535             :     DBG_CTOR( EE_ParaPortion, 0 );
     536             : 
     537      466395 :     pNode               = pN;
     538      466395 :     bInvalid            = sal_True;
     539      466395 :     bVisible            = sal_True;
     540      466395 :     bSimple             = sal_False;
     541      466395 :     bForceRepaint       = sal_False;
     542      466395 :     nInvalidPosStart    = 0;
     543      466395 :     nInvalidDiff        = 0;
     544      466395 :     nHeight             = 0;
     545      466395 :     nFirstLineOffset    = 0;
     546      466395 :     nBulletX            = 0;
     547      466395 : }
     548             : 
     549      466336 : ParaPortion::~ParaPortion()
     550             : {
     551             :     DBG_DTOR( EE_ParaPortion, 0 );
     552      466336 : }
     553             : 
     554      243687 : void ParaPortion::MarkInvalid( sal_uInt16 nStart, short nDiff )
     555             : {
     556      243687 :     if ( bInvalid == sal_False )
     557             :     {
     558             : //      nInvalidPosEnd = nStart;    // ??? => CreateLines
     559       12489 :         nInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff );
     560       12489 :         nInvalidDiff = nDiff;
     561             :     }
     562             :     else
     563             :     {
     564             :         // Simple tap in succession
     565      231911 :         if ( ( nDiff > 0 ) && ( nInvalidDiff > 0 ) &&
     566         713 :              ( ( nInvalidPosStart+nInvalidDiff ) == nStart ) )
     567             :         {
     568         712 :             nInvalidDiff = nInvalidDiff + nDiff;
     569             :         }
     570             :         // Simple delete in succession
     571      230486 :         else if ( ( nDiff < 0 ) && ( nInvalidDiff < 0 ) && ( nInvalidPosStart == nStart ) )
     572             :         {
     573           0 :             nInvalidPosStart = nInvalidPosStart + nDiff;
     574           0 :             nInvalidDiff = nInvalidDiff + nDiff;
     575             :         }
     576             :         else
     577             :         {
     578             : //          nInvalidPosEnd = pNode->Len();
     579             :             DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" );
     580      230486 :             nInvalidPosStart = std::min( nInvalidPosStart, (sal_uInt16) ( nDiff < 0 ? nStart+nDiff : nDiff ) );
     581      230486 :             nInvalidDiff = 0;
     582      230486 :             bSimple = sal_False;
     583             :         }
     584             :     }
     585      243687 :     bInvalid = sal_True;
     586      243687 :     aScriptInfos.clear();
     587      243687 :     aWritingDirectionInfos.clear();
     588      243687 : }
     589             : 
     590      782538 : void ParaPortion::MarkSelectionInvalid( sal_uInt16 nStart, sal_uInt16 /* nEnd */ )
     591             : {
     592      782538 :     if ( bInvalid == sal_False )
     593             :     {
     594       47014 :         nInvalidPosStart = nStart;
     595             : //      nInvalidPosEnd = nEnd;
     596             :     }
     597             :     else
     598             :     {
     599      735524 :         nInvalidPosStart = std::min( nInvalidPosStart, nStart );
     600             : //      nInvalidPosEnd = pNode->Len();
     601             :     }
     602      782538 :     nInvalidDiff = 0;
     603      782538 :     bInvalid = sal_True;
     604      782538 :     bSimple = sal_False;
     605      782538 :     aScriptInfos.clear();
     606      782538 :     aWritingDirectionInfos.clear();
     607      782538 : }
     608             : 
     609           0 : sal_uInt16 ParaPortion::GetLineNumber( sal_uInt16 nIndex ) const
     610             : {
     611             :     DBG_ASSERTWARNING( aLineList.Count(), "Empty ParaPortion in GetLine!" );
     612             :     DBG_ASSERT( bVisible, "Why GetLine() on an invisible paragraph?" );
     613             : 
     614           0 :     for ( sal_uInt16 nLine = 0; nLine < aLineList.Count(); nLine++ )
     615             :     {
     616           0 :         if ( aLineList[nLine]->IsIn( nIndex ) )
     617           0 :             return nLine;
     618             :     }
     619             : 
     620             :     // Then it should be at the end of the last line!
     621             :     DBG_ASSERT( nIndex == aLineList[ aLineList.Count() - 1 ]->GetEnd(), "Index dead wrong!" );
     622           0 :     return (aLineList.Count()-1);
     623             : }
     624             : 
     625           0 : void ParaPortion::SetVisible( sal_Bool bMakeVisible )
     626             : {
     627           0 :     bVisible = bMakeVisible;
     628           0 : }
     629             : 
     630           4 : void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_uInt16 nLastFormattedLine )
     631             : {
     632           4 :     sal_uInt16 nLines = aLineList.Count();
     633             :     DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Empty Portion?" );
     634           4 :     if ( nLastFormattedLine < ( nLines - 1 ) )
     635             :     {
     636           0 :         const EditLine* pLastFormatted = aLineList[ nLastFormattedLine ];
     637           0 :         const EditLine* pUnformatted = aLineList[ nLastFormattedLine+1 ];
     638           0 :         short nPortionDiff = pUnformatted->GetStartPortion() - pLastFormatted->GetEndPortion();
     639           0 :         short nTextDiff = pUnformatted->GetStart() - pLastFormatted->GetEnd();
     640           0 :         nTextDiff++;    // LastFormatted->GetEnd() was included => 1 deducted too much!
     641             : 
     642             :         // The first unformatted must begin exactly one Portion behind the last
     643             :         // of the formatted:
     644             :         // If the modified line was split into one portion, can
     645             :         // nLastEnd > nNextStart!
     646           0 :         int nPDiff = -( nPortionDiff-1 );
     647           0 :         int nTDiff = -( nTextDiff-1 );
     648           0 :         if ( nPDiff || nTDiff )
     649             :         {
     650           0 :             for ( sal_uInt16 nL = nLastFormattedLine+1; nL < nLines; nL++ )
     651             :             {
     652           0 :                 EditLine* pLine = aLineList[ nL ];
     653             : 
     654           0 :                 pLine->GetStartPortion() = sal::static_int_cast< sal_uInt16 >(
     655           0 :                     pLine->GetStartPortion() + nPDiff);
     656           0 :                 pLine->GetEndPortion() = sal::static_int_cast< sal_uInt16 >(
     657           0 :                     pLine->GetEndPortion() + nPDiff);
     658             : 
     659           0 :                 pLine->GetStart() = sal::static_int_cast< sal_uInt16 >(
     660           0 :                     pLine->GetStart() + nTDiff);
     661           0 :                 pLine->GetEnd() = sal::static_int_cast< sal_uInt16 >(
     662           0 :                     pLine->GetEnd() + nTDiff);
     663             : 
     664           0 :                 pLine->SetValid();
     665             :             }
     666             :         }
     667             :     }
     668             :     DBG_ASSERT( aLineList[ aLineList.Count()-1 ]->GetEnd() == pNode->Len(), "CorrectLines: The end is not right!" );
     669           4 : }
     670             : 
     671             : // Shared reverse lookup acceleration pieces ...
     672             : 
     673             : namespace {
     674             : 
     675             : template<typename _Array, typename _Val>
     676     5011603 : size_t FastGetPos(const _Array& rArray, const _Val* p, size_t& rLastPos)
     677             : {
     678     5011603 :     size_t nArrayLen = rArray.size();
     679             : 
     680             :     // Through certain filter code-paths we do a lot of appends, which in
     681             :     // turn call GetPos - creating some N^2 nightmares. If we have a
     682             :     // non-trivially large list, do a few checks from the end first.
     683     5011603 :     if (rLastPos > 16 && nArrayLen > 16)
     684             :     {
     685             :         size_t nEnd;
     686        1336 :         if (rLastPos > nArrayLen - 2)
     687         690 :             nEnd = nArrayLen;
     688             :         else
     689         646 :             nEnd = rLastPos + 2;
     690             : 
     691        4347 :         for (size_t nIdx = rLastPos - 2; nIdx < nEnd; ++nIdx)
     692             :         {
     693        4331 :             if (&rArray.at(nIdx) == p)
     694             :             {
     695        1320 :                 rLastPos = nIdx;
     696        1320 :                 return nIdx;
     697             :             }
     698             :         }
     699             :     }
     700             :     // The world's lamest linear search from svarray ...
     701     5287504 :     for (size_t nIdx = 0; nIdx < nArrayLen; ++nIdx)
     702     5287504 :         if (&rArray.at(nIdx) == p)
     703     5010283 :             return rLastPos = nIdx;
     704             : 
     705             :     // XXX "not found" condition for sal_Int32 indexes
     706           0 :     return EE_PARA_NOT_FOUND;
     707             : }
     708             : 
     709             : }
     710             : 
     711       19585 : ParaPortionList::ParaPortionList() : nLastCache( 0 )
     712             : {
     713       19585 : }
     714             : 
     715       19526 : ParaPortionList::~ParaPortionList()
     716             : {
     717       19526 : }
     718             : 
     719     1228108 : sal_Int32 ParaPortionList::GetPos(const ParaPortion* p) const
     720             : {
     721     1228108 :     return FastGetPos(maPortions, p, nLastCache);
     722             : }
     723             : 
     724     2508480 : ParaPortion* ParaPortionList::operator [](sal_Int32 nPos)
     725             : {
     726     2508480 :     return 0 <= nPos && static_cast<size_t>(nPos) < maPortions.size() ? &maPortions[nPos] : NULL;
     727             : }
     728             : 
     729          12 : const ParaPortion* ParaPortionList::operator [](sal_Int32 nPos) const
     730             : {
     731          12 :     return 0 <= nPos && static_cast<size_t>(nPos) < maPortions.size() ? &maPortions[nPos] : NULL;
     732             : }
     733             : 
     734           0 : ParaPortion* ParaPortionList::Release(sal_Int32 nPos)
     735             : {
     736           0 :     if (nPos < 0 || maPortions.size() <= static_cast<size_t>(nPos))
     737             :     {
     738             :         SAL_WARN( "editeng", "ParaPortionList::Release - out of bounds pos " << nPos);
     739           0 :         return NULL;
     740             :     }
     741           0 :     return maPortions.release(maPortions.begin()+nPos).release();
     742             : }
     743             : 
     744         549 : void ParaPortionList::Remove(sal_Int32 nPos)
     745             : {
     746         549 :     if (nPos < 0 || maPortions.size() <= static_cast<size_t>(nPos))
     747             :     {
     748             :         SAL_WARN( "editeng", "ParaPortionList::Remove - out of bounds pos " << nPos);
     749         549 :         return;
     750             :     }
     751         549 :     maPortions.erase(maPortions.begin()+nPos);
     752             : }
     753             : 
     754      466395 : void ParaPortionList::Insert(sal_Int32 nPos, ParaPortion* p)
     755             : {
     756      466395 :     if (nPos < 0 || maPortions.size() < static_cast<size_t>(nPos))
     757             :     {
     758             :         SAL_WARN( "editeng", "ParaPortionList::Insert - out of bounds pos " << nPos);
     759      466395 :         return;
     760             :     }
     761      466395 :     maPortions.insert(maPortions.begin()+nPos, p);
     762             : }
     763             : 
     764           0 : void ParaPortionList::Append(ParaPortion* p)
     765             : {
     766           0 :     maPortions.push_back(p);
     767           0 : }
     768             : 
     769     2563462 : sal_Int32 ParaPortionList::Count() const
     770             : {
     771     2563462 :     size_t nSize = maPortions.size();
     772     2563462 :     if (nSize > SAL_MAX_INT32)
     773             :     {
     774             :         SAL_WARN( "editeng", "ParaPortionList::Count - overflow " << nSize);
     775           0 :         return SAL_MAX_INT32;
     776             :     }
     777     2563462 :     return nSize;
     778             : }
     779             : 
     780      460309 : void ParaPortionList::Reset()
     781             : {
     782      460309 :     maPortions.clear();
     783      460309 : }
     784             : 
     785         129 : long ParaPortionList::GetYOffset(const ParaPortion* pPPortion) const
     786             : {
     787         129 :     long nHeight = 0;
     788         129 :     for (size_t i = 0, n = maPortions.size(); i < n; ++i)
     789             :     {
     790         129 :         const ParaPortion* pTmpPortion = &maPortions[i];
     791         129 :         if ( pTmpPortion == pPPortion )
     792         129 :             return nHeight;
     793           0 :         nHeight += pTmpPortion->GetHeight();
     794             :     }
     795             :     OSL_FAIL( "GetYOffset: Portion not found" );
     796           0 :     return nHeight;
     797             : }
     798             : 
     799           0 : sal_Int32 ParaPortionList::FindParagraph(long nYOffset) const
     800             : {
     801           0 :     long nY = 0;
     802           0 :     for (size_t i = 0, n = maPortions.size(); i < n; ++i)
     803             :     {
     804           0 :         nY += maPortions[i].GetHeight(); // should also be correct even in bVisible!
     805           0 :         if ( nY > nYOffset )
     806           0 :             return i <= SAL_MAX_INT32 ? static_cast<sal_Int32>(i) : SAL_MAX_INT32;
     807             :     }
     808           0 :     return EE_PARA_NOT_FOUND;
     809             : }
     810             : 
     811      910103 : const ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos) const
     812             : {
     813      910103 :     return 0 <= nPos && static_cast<size_t>(nPos) < maPortions.size() ? &maPortions[nPos] : NULL;
     814             : }
     815             : 
     816     1163622 : ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos)
     817             : {
     818     1163622 :     return 0 <= nPos && static_cast<size_t>(nPos) < maPortions.size() ? &maPortions[nPos] : NULL;
     819             : }
     820             : 
     821             : #if OSL_DEBUG_LEVEL > 2
     822             : void ParaPortionList::DbgCheck( EditDoc& rDoc)
     823             : {
     824             :     DBG_ASSERT( Count() == rDoc.Count(), "ParaPortionList::DbgCheck() - Count() unequal!" );
     825             :     for ( sal_uInt16 i = 0; i < Count(); i++ )
     826             :     {
     827             :         DBG_ASSERT( SafeGetObject(i), "ParaPortionList::DbgCheck() - Null-Pointer in List!" );
     828             :         DBG_ASSERT( GetObject(i)->GetNode(), "ParaPortionList::DbgCheck() - Null-Pointer in List(2)!" );
     829             :         DBG_ASSERT( GetObject(i)->GetNode() == rDoc.GetObject(i), "ParaPortionList::DbgCheck() - Entries intersect!" );
     830             :     }
     831             : }
     832             : #endif
     833             : 
     834        3116 : ContentAttribsInfo::ContentAttribsInfo( const SfxItemSet& rParaAttribs ) :
     835        3116 :         aPrevParaAttribs( rParaAttribs)
     836             : {
     837        3116 : }
     838             : 
     839        3116 : void ContentAttribsInfo::RemoveAllCharAttribsFromPool(SfxItemPool& rPool) const
     840             : {
     841        3116 :     CharAttribsType::const_iterator it = aPrevCharAttribs.begin(), itEnd = aPrevCharAttribs.end();
     842       24268 :     for (; it != itEnd; ++it)
     843       21152 :         rPool.Remove(*it->GetItem());
     844        3116 : }
     845             : 
     846       21152 : void ContentAttribsInfo::AppendCharAttrib(EditCharAttrib* pNew)
     847             : {
     848       21152 :     aPrevCharAttribs.push_back(pNew);
     849       21152 : }
     850             : 
     851           0 : void ConvertItem( SfxPoolItem& rPoolItem, MapUnit eSourceUnit, MapUnit eDestUnit )
     852             : {
     853             :     DBG_ASSERT( eSourceUnit != eDestUnit, "ConvertItem - Why?!" );
     854             : 
     855           0 :     switch ( rPoolItem.Which() )
     856             :     {
     857             :         case EE_PARA_LRSPACE:
     858             :         {
     859             :             DBG_ASSERT( rPoolItem.IsA( TYPE( SvxLRSpaceItem ) ), "ConvertItem: invalid Item!" );
     860           0 :             SvxLRSpaceItem& rItem = (SvxLRSpaceItem&)rPoolItem;
     861           0 :             rItem.SetTxtFirstLineOfst( sal::static_int_cast< short >( OutputDevice::LogicToLogic( rItem.GetTxtFirstLineOfst(), eSourceUnit, eDestUnit ) ) );
     862           0 :             rItem.SetTxtLeft( OutputDevice::LogicToLogic( rItem.GetTxtLeft(), eSourceUnit, eDestUnit ) );
     863           0 :             rItem.SetRight( OutputDevice::LogicToLogic( rItem.GetRight(), eSourceUnit, eDestUnit ) );
     864             :         }
     865           0 :         break;
     866             :         case EE_PARA_ULSPACE:
     867             :         {
     868             :             DBG_ASSERT( rPoolItem.IsA( TYPE( SvxULSpaceItem ) ), "ConvertItem: Invalid Item!" );
     869           0 :             SvxULSpaceItem& rItem = (SvxULSpaceItem&)rPoolItem;
     870           0 :             rItem.SetUpper( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetUpper(), eSourceUnit, eDestUnit ) ) );
     871           0 :             rItem.SetLower( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetLower(), eSourceUnit, eDestUnit ) ) );
     872             :         }
     873           0 :         break;
     874             :         case EE_PARA_SBL:
     875             :         {
     876             :             DBG_ASSERT( rPoolItem.IsA( TYPE( SvxLineSpacingItem ) ), "ConvertItem: Invalid Item!" );
     877           0 :             SvxLineSpacingItem& rItem = (SvxLineSpacingItem&)rPoolItem;
     878             :             // SetLineHeight changes also eLineSpace!
     879           0 :             if ( rItem.GetLineSpaceRule() == SVX_LINE_SPACE_MIN )
     880           0 :                 rItem.SetLineHeight( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetLineHeight(), eSourceUnit, eDestUnit ) ) );
     881             :         }
     882           0 :         break;
     883             :         case EE_PARA_TABS:
     884             :         {
     885             :             DBG_ASSERT( rPoolItem.IsA( TYPE( SvxTabStopItem ) ), "ConvertItem: Invalid Item!" );
     886           0 :             SvxTabStopItem& rItem = (SvxTabStopItem&)rPoolItem;
     887           0 :             SvxTabStopItem aNewItem( EE_PARA_TABS );
     888           0 :             for ( sal_uInt16 i = 0; i < rItem.Count(); i++ )
     889             :             {
     890           0 :                 const SvxTabStop& rTab = rItem[i];
     891           0 :                 SvxTabStop aNewStop( OutputDevice::LogicToLogic( rTab.GetTabPos(), eSourceUnit, eDestUnit ), rTab.GetAdjustment(), rTab.GetDecimal(), rTab.GetFill() );
     892           0 :                 aNewItem.Insert( aNewStop );
     893             :             }
     894           0 :             rItem = aNewItem;
     895             :         }
     896           0 :         break;
     897             :         case EE_CHAR_FONTHEIGHT:
     898             :         case EE_CHAR_FONTHEIGHT_CJK:
     899             :         case EE_CHAR_FONTHEIGHT_CTL:
     900             :         {
     901             :             DBG_ASSERT( rPoolItem.IsA( TYPE( SvxFontHeightItem ) ), "ConvertItem: Invalid Item!" );
     902           0 :             SvxFontHeightItem& rItem = (SvxFontHeightItem&)rPoolItem;
     903           0 :             rItem.SetHeight( OutputDevice::LogicToLogic( rItem.GetHeight(), eSourceUnit, eDestUnit ) );
     904             :         }
     905           0 :         break;
     906             :     }
     907           0 : }
     908             : 
     909           0 : void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const MapUnit* pSourceUnit, const MapUnit* pDestUnit )
     910             : {
     911           0 :     const SfxItemPool* pSourcePool = rSource.GetPool();
     912           0 :     const SfxItemPool* pDestPool = rDest.GetPool();
     913             : 
     914           0 :     for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
     915             :     {
     916             :         // If possible go through SlotID ...
     917             : 
     918           0 :         sal_uInt16 nSourceWhich = nWhich;
     919           0 :         sal_uInt16 nSlot = pDestPool->GetTrueSlotId( nWhich );
     920           0 :         if ( nSlot )
     921             :         {
     922           0 :             sal_uInt16 nW = pSourcePool->GetTrueWhich( nSlot );
     923           0 :             if ( nW )
     924           0 :                 nSourceWhich = nW;
     925             :         }
     926             : 
     927           0 :         if ( rSource.GetItemState( nSourceWhich, sal_False ) == SFX_ITEM_ON )
     928             :         {
     929           0 :             MapUnit eSourceUnit = pSourceUnit ? *pSourceUnit : (MapUnit)pSourcePool->GetMetric( nSourceWhich );
     930           0 :             MapUnit eDestUnit = pDestUnit ? *pDestUnit : (MapUnit)pDestPool->GetMetric( nWhich );
     931           0 :             if ( eSourceUnit != eDestUnit )
     932             :             {
     933           0 :                 SfxPoolItem* pItem = rSource.Get( nSourceWhich ).Clone();
     934             : //              pItem->SetWhich( nWhich );
     935           0 :                 ConvertItem( *pItem, eSourceUnit, eDestUnit );
     936           0 :                 rDest.Put( *pItem, nWhich );
     937           0 :                 delete pItem;
     938             :             }
     939             :             else
     940             :             {
     941           0 :                 rDest.Put( rSource.Get( nSourceWhich ), nWhich );
     942             :             }
     943             :         }
     944             :     }
     945           0 : }
     946             : 
     947      494773 : EditLine::EditLine() :
     948             :     bHangingPunctuation(false),
     949      494773 :     bInvalid(true)
     950             : {
     951             :     DBG_CTOR( EE_EditLine, 0 );
     952             : 
     953      494773 :     nStart = nEnd = 0;
     954      494773 :     nStartPortion = 0;  // to be able to tell the difference between a line
     955             :                         // without Ptorions form one with the Portion number 0
     956      494773 :     nEndPortion = 0;
     957      494773 :     nHeight = 0;
     958      494773 :     nStartPosX = 0;
     959      494773 :     nTxtHeight = 0;
     960      494773 :     nTxtWidth = 0;
     961      494773 :     nCrsrHeight = 0;
     962      494773 :     nMaxAscent = 0;
     963      494773 : }
     964             : 
     965      138591 : EditLine::EditLine( const EditLine& r ) :
     966             :     bHangingPunctuation(r.bHangingPunctuation),
     967      138591 :     bInvalid(true)
     968             : {
     969             :     DBG_CTOR( EE_EditLine, 0 );
     970             : 
     971      138591 :     nEnd = r.nEnd;
     972      138591 :     nStart = r.nStart;
     973      138591 :     nStartPortion = r.nStartPortion;
     974      138591 :     nEndPortion = r.nEndPortion;
     975             : 
     976      138591 :     nHeight = 0;
     977      138591 :     nStartPosX = 0;
     978      138591 :     nTxtHeight = 0;
     979      138591 :     nTxtWidth = 0;
     980      138591 :     nCrsrHeight = 0;
     981      138591 :     nMaxAscent = 0;
     982      138591 : }
     983             : 
     984      633328 : EditLine::~EditLine()
     985             : {
     986             :     DBG_DTOR( EE_EditLine, 0 );
     987      633328 : }
     988             : 
     989      704640 : EditLine::CharPosArrayType& EditLine::GetCharPosArray()
     990             : {
     991      704640 :     return aPositions;
     992             : }
     993             : 
     994       22158 : const EditLine::CharPosArrayType& EditLine::GetCharPosArray() const
     995             : {
     996       22158 :     return aPositions;
     997             : }
     998             : 
     999           0 : EditLine* EditLine::Clone() const
    1000             : {
    1001           0 :     EditLine* pL = new EditLine;
    1002           0 :     pL->aPositions = aPositions;
    1003           0 :     pL->nStartPosX      = nStartPosX;
    1004           0 :     pL->nStart          = nStart;
    1005           0 :     pL->nEnd            = nEnd;
    1006           0 :     pL->nStartPortion   = nStartPortion;
    1007           0 :     pL->nEndPortion     = nEndPortion;
    1008           0 :     pL->nHeight         = nHeight;
    1009           0 :     pL->nTxtWidth       = nTxtWidth;
    1010           0 :     pL->nTxtHeight      = nTxtHeight;
    1011           0 :     pL->nCrsrHeight     = nCrsrHeight;
    1012           0 :     pL->nMaxAscent      = nMaxAscent;
    1013             : 
    1014           0 :     return pL;
    1015             : }
    1016             : 
    1017           0 : sal_Bool operator == ( const EditLine& r1,  const EditLine& r2  )
    1018             : {
    1019           0 :     if ( r1.nStart != r2.nStart )
    1020           0 :         return sal_False;
    1021             : 
    1022           0 :     if ( r1.nEnd != r2.nEnd )
    1023           0 :         return sal_False;
    1024             : 
    1025           0 :     if ( r1.nStartPortion != r2.nStartPortion )
    1026           0 :         return sal_False;
    1027             : 
    1028           0 :     if ( r1.nEndPortion != r2.nEndPortion )
    1029           0 :         return sal_False;
    1030             : 
    1031           0 :     return sal_True;
    1032             : }
    1033             : 
    1034       46694 : EditLine& EditLine::operator = ( const EditLine& r )
    1035             : {
    1036       46694 :     nEnd = r.nEnd;
    1037       46694 :     nStart = r.nStart;
    1038       46694 :     nEndPortion = r.nEndPortion;
    1039       46694 :     nStartPortion = r.nStartPortion;
    1040       46694 :     return *this;
    1041             : }
    1042             : 
    1043             : 
    1044           0 : sal_Bool operator != ( const EditLine& r1,  const EditLine& r2  )
    1045             : {
    1046           0 :     return !( r1 == r2 );
    1047             : }
    1048             : 
    1049      595383 : void EditLine::SetHeight( sal_uInt16 nH, sal_uInt16 nTxtH, sal_uInt16 nCrsrH )
    1050             : {
    1051      595383 :     nHeight = nH;
    1052      595383 :     nTxtHeight = ( nTxtH ? nTxtH : nH );
    1053      595383 :     nCrsrHeight = ( nCrsrH ? nCrsrH : nTxtHeight );
    1054      595383 : }
    1055             : 
    1056      497539 : void EditLine::SetStartPosX( long start )
    1057             : {
    1058      497539 :     if (start > 0)
    1059       98910 :         nStartPosX = start;
    1060             :     else
    1061      398629 :         nStartPosX = 0;
    1062      497539 : }
    1063             : 
    1064      185285 : Size EditLine::CalcTextSize( ParaPortion& rParaPortion )
    1065             : {
    1066      185285 :     Size aSz;
    1067      185285 :     Size aTmpSz;
    1068             :     TextPortion* pPortion;
    1069             : 
    1070      185285 :     sal_uInt16 nIndex = GetStart();
    1071             : 
    1072             :     DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize before CreatePortions !" );
    1073             : 
    1074      376148 :     for ( sal_uInt16 n = nStartPortion; n <= nEndPortion; n++ )
    1075             :     {
    1076      190863 :         pPortion = rParaPortion.GetTextPortions()[n];
    1077      190863 :         switch ( pPortion->GetKind() )
    1078             :         {
    1079             :             case PORTIONKIND_TEXT:
    1080             :             case PORTIONKIND_FIELD:
    1081             :             case PORTIONKIND_HYPHENATOR:
    1082             :             {
    1083      190838 :                 aTmpSz = pPortion->GetSize();
    1084      190838 :                 aSz.Width() += aTmpSz.Width();
    1085      190838 :                 if ( aSz.Height() < aTmpSz.Height() )
    1086      185290 :                     aSz.Height() = aTmpSz.Height();
    1087             :             }
    1088      190838 :             break;
    1089             :             case PORTIONKIND_TAB:
    1090             :             {
    1091           4 :                 aSz.Width() += pPortion->GetSize().Width();
    1092             :             }
    1093           4 :             break;
    1094             :         }
    1095      190863 :         nIndex = nIndex + pPortion->GetLen();
    1096             :     }
    1097             : 
    1098      185285 :     SetHeight( (sal_uInt16)aSz.Height() );
    1099      185285 :     return aSz;
    1100             : }
    1101             : 
    1102      466395 : EditLineList::EditLineList()
    1103             : {
    1104      466395 : }
    1105             : 
    1106      932672 : EditLineList::~EditLineList()
    1107             : {
    1108      466336 :     Reset();
    1109      466336 : }
    1110             : 
    1111      506553 : void EditLineList::Reset()
    1112             : {
    1113      506553 :     maLines.clear();
    1114      506553 : }
    1115             : 
    1116           2 : void EditLineList::DeleteFromLine(size_t nDelFrom)
    1117             : {
    1118             :     DBG_ASSERT( nDelFrom <= (maLines.size() - 1), "DeleteFromLine: Out of range" );
    1119           2 :     LinesType::iterator it = maLines.begin();
    1120           2 :     std::advance(it, nDelFrom);
    1121           2 :     maLines.erase(it, maLines.end());
    1122           2 : }
    1123             : 
    1124          16 : size_t EditLineList::FindLine(sal_uInt16 nChar, bool bInclEnd)
    1125             : {
    1126          16 :     size_t n = maLines.size();
    1127          16 :     for (size_t i = 0; i < n; ++i)
    1128             :     {
    1129          16 :         const EditLine& rLine = maLines[i];
    1130          24 :         if ( (bInclEnd && (rLine.GetEnd() >= nChar)) ||
    1131           8 :              (rLine.GetEnd() > nChar) )
    1132             :         {
    1133          16 :             return i;
    1134             :         }
    1135             :     }
    1136             : 
    1137             :     DBG_ASSERT( !bInclEnd, "Line not found: FindLine" );
    1138           0 :     return n - 1;
    1139             : }
    1140             : 
    1141     4057641 : size_t EditLineList::Count() const
    1142             : {
    1143     4057641 :     return maLines.size();
    1144             : }
    1145             : 
    1146       12560 : const EditLine* EditLineList::operator[](size_t nPos) const
    1147             : {
    1148       12560 :     return &maLines[nPos];
    1149             : }
    1150             : 
    1151     1762243 : EditLine* EditLineList::operator[](size_t nPos)
    1152             : {
    1153     1762243 :     return &maLines[nPos];
    1154             : }
    1155             : 
    1156      448098 : void EditLineList::Append(EditLine* p)
    1157             : {
    1158      448098 :     maLines.push_back(p);
    1159      448098 : }
    1160             : 
    1161       46675 : void EditLineList::Insert(size_t nPos, EditLine* p)
    1162             : {
    1163       46675 :     maLines.insert(maLines.begin()+nPos, p);
    1164       46675 : }
    1165             : 
    1166     2475604 : EditPaM::EditPaM() : pNode(NULL), nIndex(0) {}
    1167     1745469 : EditPaM::EditPaM(const EditPaM& r) : pNode(r.pNode), nIndex(r.nIndex) {}
    1168     2297274 : EditPaM::EditPaM(ContentNode* p, sal_uInt16 n) : pNode(p), nIndex(n) {}
    1169             : 
    1170     2198049 : const ContentNode* EditPaM::GetNode() const
    1171             : {
    1172     2198049 :     return pNode;
    1173             : }
    1174             : 
    1175     5131778 : ContentNode* EditPaM::GetNode()
    1176             : {
    1177     5131778 :     return pNode;
    1178             : }
    1179             : 
    1180       53657 : void EditPaM::SetNode(ContentNode* p)
    1181             : {
    1182       53657 :     pNode = p;
    1183       53657 : }
    1184             : 
    1185           0 : sal_Bool EditPaM::DbgIsBuggy( EditDoc& rDoc )
    1186             : {
    1187           0 :     if ( !pNode )
    1188           0 :         return sal_True;
    1189           0 :     if ( rDoc.GetPos( pNode ) >= rDoc.Count() )
    1190           0 :         return sal_True;
    1191           0 :     if ( nIndex > pNode->Len() )
    1192           0 :         return sal_True;
    1193             : 
    1194           0 :     return sal_False;
    1195             : }
    1196             : 
    1197           0 : sal_Bool EditSelection::DbgIsBuggy( EditDoc& rDoc )
    1198             : {
    1199           0 :     if ( aStartPaM.DbgIsBuggy( rDoc ) )
    1200           0 :         return sal_True;
    1201           0 :     if ( aEndPaM.DbgIsBuggy( rDoc ) )
    1202           0 :         return sal_True;
    1203             : 
    1204           0 :     return sal_False;
    1205             : }
    1206             : 
    1207      105708 : EditSelection::EditSelection()
    1208             : {
    1209      105708 : }
    1210             : 
    1211      224172 : EditSelection::EditSelection( const EditPaM& rStartAndAnd )
    1212             : {
    1213             :     // could still be optimized!
    1214             :     // do no first call the Def-constructor from PaM!
    1215      224172 :     aStartPaM = rStartAndAnd;
    1216      224172 :     aEndPaM = rStartAndAnd;
    1217      224172 : }
    1218             : 
    1219      886057 : EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd )
    1220             : {
    1221             :     // could still be optimized!
    1222      886057 :     aStartPaM = rStart;
    1223      886057 :     aEndPaM = rEnd;
    1224      886057 : }
    1225             : 
    1226        5408 : EditSelection& EditSelection::operator = ( const EditPaM& rPaM )
    1227             : {
    1228        5408 :     aStartPaM = rPaM;
    1229        5408 :     aEndPaM = rPaM;
    1230        5408 :     return *this;
    1231             : }
    1232             : 
    1233           0 : sal_Bool EditSelection::IsInvalid() const
    1234             : {
    1235           0 :     EditPaM aEmptyPaM;
    1236             : 
    1237           0 :     if ( aStartPaM == aEmptyPaM )
    1238           0 :         return sal_True;
    1239             : 
    1240           0 :     if ( aEndPaM == aEmptyPaM )
    1241           0 :         return sal_True;
    1242             : 
    1243           0 :     return sal_False;
    1244             : }
    1245             : 
    1246      312133 : sal_Bool EditSelection::Adjust( const EditDoc& rNodes )
    1247             : {
    1248             :     DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in Adjust(1)" );
    1249             :     DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index out of range in Adjust(2)" );
    1250             : 
    1251      312133 :     const ContentNode* pStartNode = aStartPaM.GetNode();
    1252      312133 :     const ContentNode* pEndNode = aEndPaM.GetNode();
    1253             : 
    1254      312133 :     sal_Int32 nStartNode = rNodes.GetPos( pStartNode );
    1255      312133 :     sal_Int32 nEndNode = rNodes.GetPos( pEndNode );
    1256             : 
    1257             :     DBG_ASSERT( nStartNode != SAL_MAX_INT32, "Node out of range in Adjust(1)" );
    1258             :     DBG_ASSERT( nEndNode != SAL_MAX_INT32, "Node out of range in Adjust(2)" );
    1259             : 
    1260      312133 :     sal_Bool bSwap = sal_False;
    1261      312133 :     if ( nStartNode > nEndNode )
    1262           0 :         bSwap = sal_True;
    1263      312133 :     else if ( ( nStartNode == nEndNode ) && ( aStartPaM.GetIndex() > aEndPaM.GetIndex() ) )
    1264           0 :         bSwap = sal_True;
    1265             : 
    1266      312133 :     if ( bSwap )
    1267             :     {
    1268           0 :         EditPaM aTmpPaM( aStartPaM );
    1269           0 :         aStartPaM = aEndPaM;
    1270           0 :         aEndPaM = aTmpPaM;
    1271             :     }
    1272             : 
    1273      312133 :     return bSwap;
    1274             : }
    1275             : 
    1276      260309 : sal_Bool operator == ( const EditPaM& r1,  const EditPaM& r2  )
    1277             : {
    1278      260309 :     if ( r1.GetNode() != r2.GetNode() )
    1279         957 :         return sal_False;
    1280             : 
    1281      259352 :     if ( r1.GetIndex() != r2.GetIndex() )
    1282        5627 :         return sal_False;
    1283             : 
    1284      253725 :     return sal_True;
    1285             : }
    1286             : 
    1287     3066246 : EditPaM& EditPaM::operator = ( const EditPaM& rPaM )
    1288             : {
    1289     3066246 :     nIndex = rPaM.nIndex;
    1290     3066246 :     pNode = rPaM.pNode;
    1291     3066246 :     return *this;
    1292             : }
    1293             : 
    1294      260309 : sal_Bool operator != ( const EditPaM& r1,  const EditPaM& r2  )
    1295             : {
    1296      260309 :     return !( r1 == r2 );
    1297             : }
    1298             : 
    1299      465080 : ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool )
    1300             : {
    1301             :     DBG_CTOR( EE_ContentNode, 0 );
    1302      465080 :     pWrongList = NULL;
    1303      465080 : }
    1304             : 
    1305        1315 : ContentNode::ContentNode( const XubString& rStr, const ContentAttribs& rContentAttribs ) :
    1306        1315 :     maString(rStr), aContentAttribs(rContentAttribs)
    1307             : {
    1308             :     DBG_CTOR( EE_ContentNode, 0 );
    1309        1315 :     pWrongList = NULL;
    1310        1315 : }
    1311             : 
    1312      932672 : ContentNode::~ContentNode()
    1313             : {
    1314             :     DBG_DTOR( EE_ContentNode, 0 );
    1315      466336 :     delete pWrongList;
    1316      466336 : }
    1317             : 
    1318      242213 : void ContentNode::ExpandAttribs( sal_uInt16 nIndex, sal_uInt16 nNew, SfxItemPool& rItemPool )
    1319             : {
    1320      242213 :     if ( !nNew )
    1321      308898 :         return;
    1322             : 
    1323             :     // Since features are treated differently than normal character attributes,
    1324             :     // can also the order of the start list be change!
    1325             :     // In every if ...,  in the next (n) opportunities due to bFeature or
    1326             :     // an existing special case, must (n-1) opportunities be provided with
    1327             :     // bResort. The most likely possibility receives no bResort, so that is
    1328             :     // not sorted anew when all attributes are the same.
    1329      175528 :     bool bResort = false;
    1330      175528 :     bool bExpandedEmptyAtIndexNull = false;
    1331             : 
    1332      175528 :     size_t nAttr = 0;
    1333      175528 :     CharAttribList::AttribsType& rAttribs = aCharAttribList.GetAttribs();
    1334      175528 :     EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr);
    1335      353588 :     while ( pAttrib )
    1336             :     {
    1337        2532 :         if ( pAttrib->GetEnd() >= nIndex )
    1338             :         {
    1339             :             // Move all attributes behind the insertion point...
    1340        2211 :             if ( pAttrib->GetStart() > nIndex )
    1341             :             {
    1342         939 :                 pAttrib->MoveForward( nNew );
    1343             :             }
    1344             :             // 0: Expand empty attribute, if at insertion point
    1345        1272 :             else if ( pAttrib->IsEmpty() )
    1346             :             {
    1347             :                 // Do not check Index, a emty one could only be there
    1348             :                 // When later checking it anyhow:
    1349             :                 //   Special caase: Start == 0; AbsLen == 1, nNew = 1
    1350             :                 // => Expand, because of paragraph break!
    1351             :                 // Start <= nIndex, End >= nIndex => Start=End=nIndex!
    1352             : //              if ( pAttrib->GetStart() == nIndex )
    1353         750 :                 pAttrib->Expand( nNew );
    1354         750 :                 if ( pAttrib->GetStart() == 0 )
    1355         717 :                     bExpandedEmptyAtIndexNull = sal_True;
    1356             :             }
    1357             :             // 1: Attribute starts before, goes to index ...
    1358         522 :             else if ( pAttrib->GetEnd() == nIndex ) // Start must be before
    1359             :             {
    1360             :                 // Only expand when there is no feature
    1361             :                 // and if not in exclude list!
    1362             :                 // Otherwise, a UL will go on until a new ULDB, expaning both
    1363             : //              if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) )
    1364         519 :                 if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) )
    1365             :                 {
    1366         185 :                     if ( !pAttrib->IsEdge() )
    1367         185 :                         pAttrib->Expand( nNew );
    1368             :                 }
    1369             :                 else
    1370         334 :                     bResort = sal_True;
    1371             :             }
    1372             :             // 2: Attribute starts before, goes past the Index...
    1373           3 :             else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
    1374             :             {
    1375             :                 DBG_ASSERT( !pAttrib->IsFeature(), "Large Feature?!" );
    1376           0 :                 pAttrib->Expand( nNew );
    1377             :             }
    1378             :             // 3: Attribute starts on index...
    1379           3 :             else if ( pAttrib->GetStart() == nIndex )
    1380             :             {
    1381           3 :                 if ( pAttrib->IsFeature() )
    1382             :                 {
    1383           3 :                     pAttrib->MoveForward( nNew );
    1384           3 :                     bResort = sal_True;
    1385             :                 }
    1386             :                 else
    1387             :                 {
    1388           0 :                     bool bExpand = false;
    1389           0 :                     if ( nIndex == 0 )
    1390             :                     {
    1391           0 :                         bExpand = sal_True;
    1392           0 :                         if( bExpandedEmptyAtIndexNull )
    1393             :                         {
    1394             :                             // Check if this kind of attribut was empty and expanded here...
    1395           0 :                             sal_uInt16 nW = pAttrib->GetItem()->Which();
    1396           0 :                             for ( sal_uInt16 nA = 0; nA < nAttr; nA++ )
    1397             :                             {
    1398           0 :                                 const EditCharAttrib& r = aCharAttribList.GetAttribs()[nA];
    1399           0 :                                 if ( ( r.GetStart() == 0 ) && ( r.GetItem()->Which() == nW ) )
    1400             :                                 {
    1401           0 :                                     bExpand = false;
    1402           0 :                                     break;
    1403             :                                 }
    1404             :                             }
    1405             : 
    1406             :                         }
    1407             :                     }
    1408           0 :                     if ( bExpand )
    1409             :                     {
    1410           0 :                         pAttrib->Expand( nNew );
    1411           0 :                         bResort = true;
    1412             :                     }
    1413             :                     else
    1414             :                     {
    1415           0 :                         pAttrib->MoveForward( nNew );
    1416             :                     }
    1417             :                 }
    1418             :             }
    1419             :         }
    1420             : 
    1421        2532 :         if ( pAttrib->IsEdge() )
    1422           0 :             pAttrib->SetEdge(false);
    1423             : 
    1424             :         DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
    1425             : 
    1426             :         DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribute distorted!" );
    1427             :         DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attribute larger than paragraph!" );
    1428        2532 :         if ( pAttrib->IsEmpty() )
    1429             :         {
    1430             :             OSL_FAIL( "Empty Attribute after ExpandAttribs?" );
    1431           0 :             bResort = true;
    1432           0 :             rItemPool.Remove( *pAttrib->GetItem() );
    1433           0 :             rAttribs.erase(rAttribs.begin()+nAttr);
    1434           0 :             --nAttr;
    1435             :         }
    1436        2532 :         ++nAttr;
    1437        2532 :         pAttrib = GetAttrib(rAttribs, nAttr);
    1438             :     }
    1439             : 
    1440      175528 :     if ( bResort )
    1441         333 :         aCharAttribList.ResortAttribs();
    1442             : 
    1443      175528 :     if ( pWrongList )
    1444             :     {
    1445       90255 :         bool bSep = ( maString.GetChar( nIndex ) == ' ' ) || IsFeature( nIndex );
    1446       90255 :         pWrongList->TextInserted( nIndex, nNew, bSep );
    1447             :     }
    1448             : 
    1449             : #if OSL_DEBUG_LEVEL > 2
    1450             :     OSL_ENSURE( CheckOrderedList( aCharAttribList.GetAttribs(), sal_True ), "Expand: Start List distorted" );
    1451             : #endif
    1452             : }
    1453             : 
    1454        1268 : void ContentNode::CollapsAttribs( sal_uInt16 nIndex, sal_uInt16 nDeleted, SfxItemPool& rItemPool )
    1455             : {
    1456        1268 :     if ( !nDeleted )
    1457        2351 :         return;
    1458             : 
    1459             :     // Since features are treated differently than normal character attributes,
    1460             :     // can also the order of the start list be change!
    1461         185 :     bool bResort = false;
    1462         185 :     bool bDelAttr = false;
    1463         185 :     sal_uInt16 nEndChanges = nIndex+nDeleted;
    1464             : 
    1465         185 :     size_t nAttr = 0;
    1466         185 :     CharAttribList::AttribsType& rAttribs = aCharAttribList.GetAttribs();
    1467         185 :     EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr);
    1468         504 :     while ( pAttrib )
    1469             :     {
    1470         134 :         bDelAttr = false;
    1471         134 :         if ( pAttrib->GetEnd() >= nIndex )
    1472             :         {
    1473             :             // Move all Attribute behind the insert point...
    1474         134 :             if ( pAttrib->GetStart() >= nEndChanges )
    1475             :             {
    1476           4 :                 pAttrib->MoveBackward( nDeleted );
    1477             :             }
    1478             :             // 1. Delete Internal attributes...
    1479         130 :             else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) )
    1480             :             {
    1481             :                 // Special case: Attribute covers the area exactly
    1482             :                 // => keep as empty Attribute.
    1483          93 :                 if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) )
    1484          25 :                     pAttrib->GetEnd() = nIndex; // empty
    1485             :                 else
    1486          68 :                     bDelAttr = sal_True;
    1487             :             }
    1488             :             // 2. Attribute starts earlier, ends inside or behind it ...
    1489          37 :             else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
    1490             :             {
    1491             :                 DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" );
    1492          21 :                 if ( pAttrib->GetEnd() <= nEndChanges ) // ends inside
    1493           0 :                     pAttrib->GetEnd() = nIndex;
    1494             :                 else
    1495          21 :                     pAttrib->Collaps( nDeleted );       // ends behind
    1496             :             }
    1497             :             // 3. Attribute starts inside, ending behind ...
    1498          16 :             else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) )
    1499             :             {
    1500             :                 // Features not allowed to expand!
    1501           0 :                 if ( pAttrib->IsFeature() )
    1502             :                 {
    1503           0 :                     pAttrib->MoveBackward( nDeleted );
    1504           0 :                     bResort = sal_True;
    1505             :                 }
    1506             :                 else
    1507             :                 {
    1508           0 :                     pAttrib->GetStart() = nEndChanges;
    1509           0 :                     pAttrib->MoveBackward( nDeleted );
    1510             :                 }
    1511             :             }
    1512             :         }
    1513             :         DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
    1514             : 
    1515             :         DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut distorted!" );
    1516             :         DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collaps: Attribute larger than paragraph!" );
    1517         134 :         if ( bDelAttr )
    1518             :         {
    1519          68 :             bResort = true;
    1520          68 :             rItemPool.Remove( *pAttrib->GetItem() );
    1521          68 :             rAttribs.erase(rAttribs.begin()+nAttr);
    1522          68 :             nAttr--;
    1523             :         }
    1524          66 :         else if ( pAttrib->IsEmpty() )
    1525          25 :             aCharAttribList.SetHasEmptyAttribs(true);
    1526             : 
    1527         134 :         nAttr++;
    1528         134 :         pAttrib = GetAttrib(rAttribs, nAttr);
    1529             :     }
    1530             : 
    1531         185 :     if ( bResort )
    1532          65 :         aCharAttribList.ResortAttribs();
    1533             : 
    1534         185 :     if ( pWrongList )
    1535          47 :         pWrongList->TextDeleted( nIndex, nDeleted );
    1536             : 
    1537             : #if OSL_DEBUG_LEVEL > 2
    1538             :     OSL_ENSURE( CheckOrderedList( aCharAttribList.GetAttribs(), sal_True ), "Collaps: Start list distorted" );
    1539             : #endif
    1540             : }
    1541             : 
    1542        1315 : void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, sal_Bool bKeepEndingAttribs )
    1543             : {
    1544             :     DBG_ASSERT( pPrevNode, "Copy of attributes to a null pointer?" );
    1545             : 
    1546        1315 :     sal_uInt16 nCut = pPrevNode->Len();
    1547             : 
    1548        1315 :     size_t nAttr = 0;
    1549        1315 :     CharAttribList::AttribsType& rPrevAttribs = pPrevNode->GetCharAttribs().GetAttribs();
    1550        1315 :     EditCharAttrib* pAttrib = GetAttrib(rPrevAttribs, nAttr);
    1551        5704 :     while ( pAttrib )
    1552             :     {
    1553        3074 :         if ( pAttrib->GetEnd() < nCut )
    1554             :         {
    1555             :             // remain unchanged ....
    1556             :             ;
    1557             :         }
    1558        2373 :         else if ( pAttrib->GetEnd() == nCut )
    1559             :         {
    1560             :             // must be copied as an empty attributes.
    1561        2372 :             if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) )
    1562             :             {
    1563        2021 :                 EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 );
    1564             :                 DBG_ASSERT( pNewAttrib, "MakeCharAttrib failed!" );
    1565        2021 :                 aCharAttribList.InsertAttrib( pNewAttrib );
    1566             :             }
    1567             :         }
    1568           1 :         else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) )
    1569             :         {
    1570             :             // If cut is done right at the front then the attribute must be
    1571             :             // kept! Has to be copied and changed.
    1572           0 :             EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut );
    1573             :             DBG_ASSERT( pNewAttrib, "MakeCharAttrib failed!" );
    1574           0 :             aCharAttribList.InsertAttrib( pNewAttrib );
    1575           0 :             pAttrib->GetEnd() = nCut;
    1576             :         }
    1577             :         else
    1578             :         {
    1579             :             // Move all attributes in the current node (this)
    1580           1 :             CharAttribList::AttribsType::iterator it = rPrevAttribs.begin() + nAttr;
    1581           1 :             aCharAttribList.InsertAttrib(rPrevAttribs.release(it).release());
    1582             : 
    1583             :             DBG_ASSERT( pAttrib->GetStart() >= nCut, "Start < nCut!" );
    1584             :             DBG_ASSERT( pAttrib->GetEnd() >= nCut, "End < nCut!" );
    1585           1 :             pAttrib->GetStart() = pAttrib->GetStart() - nCut;
    1586           1 :             pAttrib->GetEnd() = pAttrib->GetEnd() - nCut;
    1587           1 :             nAttr--;
    1588             :         }
    1589        3074 :         nAttr++;
    1590        3074 :         pAttrib = GetAttrib(rPrevAttribs, nAttr);
    1591             :     }
    1592        1315 : }
    1593             : 
    1594         543 : void ContentNode::AppendAttribs( ContentNode* pNextNode )
    1595             : {
    1596             :     DBG_ASSERT( pNextNode, "Copy of attributes to a null pointer?" );
    1597             : 
    1598         543 :     sal_uInt16 nNewStart = maString.Len();
    1599             : 
    1600             : #if OSL_DEBUG_LEVEL > 2
    1601             :     OSL_ENSURE( aCharAttribList.DbgCheckAttribs(), "Attribute before AppendAttribs broken" );
    1602             : #endif
    1603             : 
    1604         543 :     size_t nAttr = 0;
    1605         543 :     CharAttribList::AttribsType& rNextAttribs = pNextNode->GetCharAttribs().GetAttribs();
    1606         543 :     EditCharAttrib* pAttrib = GetAttrib(rNextAttribs, nAttr);
    1607        1097 :     while ( pAttrib )
    1608             :     {
    1609             :         // Move all attributes in the current node (this)
    1610          11 :         bool bMelted = false;
    1611          11 :         if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) )
    1612             :         {
    1613             :             // Attributes can possibly be summarized as:
    1614          11 :             size_t nTmpAttr = 0;
    1615          11 :             EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
    1616          31 :             while ( !bMelted && pTmpAttrib )
    1617             :             {
    1618           9 :                 if ( pTmpAttrib->GetEnd() == nNewStart )
    1619             :                 {
    1620          15 :                     if ( ( pTmpAttrib->Which() == pAttrib->Which() ) &&
    1621           6 :                          ( *(pTmpAttrib->GetItem()) == *(pAttrib->GetItem() ) ) )
    1622             :                     {
    1623           6 :                         pTmpAttrib->GetEnd() =
    1624           6 :                             pTmpAttrib->GetEnd() + pAttrib->GetLen();
    1625           6 :                         rNextAttribs.erase(rNextAttribs.begin()+nAttr);
    1626             :                         // Unsubscribe from the pool?!
    1627           6 :                         bMelted = true;
    1628             :                     }
    1629             :                 }
    1630           9 :                 ++nTmpAttr;
    1631           9 :                 pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
    1632             :             }
    1633             :         }
    1634             : 
    1635          11 :         if ( !bMelted )
    1636             :         {
    1637           5 :             pAttrib->GetStart() = pAttrib->GetStart() + nNewStart;
    1638           5 :             pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart;
    1639           5 :             CharAttribList::AttribsType::iterator it = rNextAttribs.begin() + nAttr;
    1640           5 :             aCharAttribList.InsertAttrib(rNextAttribs.release(it).release());
    1641             :         }
    1642          11 :         pAttrib = GetAttrib(rNextAttribs, nAttr);
    1643             :     }
    1644             :     // For the Attributes that just moved over:
    1645         543 :     rNextAttribs.clear();
    1646             : 
    1647             : #if OSL_DEBUG_LEVEL > 2
    1648             :     OSL_ENSURE( aCharAttribList.DbgCheckAttribs(), "Attribute after AppendAttribs broken" );
    1649             : #endif
    1650         543 : }
    1651             : 
    1652      579152 : void ContentNode::CreateDefFont()
    1653             : {
    1654             :     // First use the information from the style ...
    1655      579152 :     SfxStyleSheet* pS = aContentAttribs.GetStyleSheet();
    1656      579152 :     if ( pS )
    1657      205053 :         CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() );
    1658             : 
    1659             :     // ... then iron out the hard paragraph formatting...
    1660      579152 :     CreateFont( GetCharAttribs().GetDefFont(),
    1661     1158304 :         GetContentAttribs().GetItems(), pS == NULL );
    1662      579152 : }
    1663             : 
    1664           0 : void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle )
    1665             : {
    1666           0 :     aContentAttribs.SetStyleSheet( pS );
    1667             : 
    1668             : 
    1669             :     // First use the information from the style ...
    1670           0 :     GetCharAttribs().GetDefFont() = rFontFromStyle;
    1671             :     // ... then iron out the hard paragraph formatting...
    1672           0 :     CreateFont( GetCharAttribs().GetDefFont(),
    1673           0 :         GetContentAttribs().GetItems(), pS == NULL );
    1674           0 : }
    1675             : 
    1676      324907 : void ContentNode::SetStyleSheet( SfxStyleSheet* pS, sal_Bool bRecalcFont )
    1677             : {
    1678      324907 :     aContentAttribs.SetStyleSheet( pS );
    1679      324907 :     if ( bRecalcFont )
    1680      101651 :         CreateDefFont();
    1681      324907 : }
    1682             : 
    1683      104563 : void ContentNode::DestroyWrongList()
    1684             : {
    1685      104563 :     delete pWrongList;
    1686      104563 :     pWrongList = NULL;
    1687      104563 : }
    1688             : 
    1689       90161 : bool ContentNode::IsFeature( sal_uInt16 nPos ) const
    1690             : {
    1691       90161 :     return maString.GetChar(nPos) == CH_FEATURE;
    1692             : }
    1693             : 
    1694     8375829 : sal_uInt16 ContentNode::Len() const
    1695             : {
    1696     8375829 :     return maString.Len();
    1697             : }
    1698             : 
    1699      521755 : const XubString& ContentNode::GetString() const
    1700             : {
    1701      521755 :     return maString;
    1702             : }
    1703             : 
    1704           0 : void ContentNode::SetChar(sal_uInt16 nPos, sal_Unicode c)
    1705             : {
    1706           0 :     maString.SetChar(nPos, c);
    1707           0 : }
    1708             : 
    1709      242213 : void ContentNode::Insert(const XubString& rStr, sal_uInt16 nPos)
    1710             : {
    1711      242213 :     maString.Insert(rStr, nPos);
    1712      242213 : }
    1713             : 
    1714         543 : void ContentNode::Append(const XubString& rStr)
    1715             : {
    1716         543 :     maString.Append(rStr);
    1717         543 : }
    1718             : 
    1719        1315 : void ContentNode::Erase(sal_uInt16 nPos)
    1720             : {
    1721        1315 :     maString.Erase(nPos);
    1722        1315 : }
    1723             : 
    1724        1268 : void ContentNode::Erase(sal_uInt16 nPos, sal_uInt16 nCount)
    1725             : {
    1726        1268 :     maString.Erase(nPos, nCount);
    1727        1268 : }
    1728             : 
    1729        1315 : XubString ContentNode::Copy(sal_uInt16 nPos) const
    1730             : {
    1731        1315 :     return maString.Copy(nPos);
    1732             : }
    1733             : 
    1734       46374 : XubString ContentNode::Copy(sal_uInt16 nPos, sal_uInt16 nCount) const
    1735             : {
    1736       46374 :     return maString.Copy(nPos, nCount);
    1737             : }
    1738             : 
    1739      117239 : sal_Unicode ContentNode::GetChar(sal_uInt16 nPos) const
    1740             : {
    1741      117239 :     return maString.GetChar(nPos);
    1742             : }
    1743             : 
    1744      302141 : void ContentNode::CreateWrongList()
    1745             : {
    1746             :     DBG_ASSERT( !pWrongList, "WrongList already exist!" );
    1747      302141 :     pWrongList = new WrongList;
    1748      302141 : }
    1749             : 
    1750      104416 : void ContentNode::SetWrongList( WrongList* p )
    1751             : {
    1752             :     DBG_ASSERT( !pWrongList, "WrongList already exist!" );
    1753      104416 :     pWrongList = p;
    1754      104416 : }
    1755             : 
    1756      465080 : ContentAttribs::ContentAttribs( SfxItemPool& rPool ) :
    1757      465080 :                     aAttribSet( rPool, EE_PARA_START, EE_CHAR_END )
    1758             : {
    1759      465080 :     pStyle = 0;
    1760      465080 : }
    1761             : 
    1762        2630 : ContentAttribs::ContentAttribs( const ContentAttribs& rRef ) :
    1763        2630 :                     aAttribSet( rRef.aAttribSet )
    1764             : {
    1765        2630 :     pStyle = rRef.pStyle;
    1766        2630 : }
    1767             : 
    1768      467651 : ContentAttribs::~ContentAttribs()
    1769             : {
    1770      467651 : }
    1771             : 
    1772           4 : SvxTabStop ContentAttribs::FindTabStop( long nCurPos, sal_uInt16 nDefTab )
    1773             : {
    1774           4 :     const SvxTabStopItem& rTabs = (const SvxTabStopItem&) GetItem( EE_PARA_TABS );
    1775           6 :     for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ )
    1776             :     {
    1777           4 :         const SvxTabStop& rTab = rTabs[i];
    1778           4 :         if ( rTab.GetTabPos() > nCurPos  )
    1779           2 :             return rTab;
    1780             :     }
    1781             : 
    1782             :     // Determine DefTab ...
    1783           2 :     SvxTabStop aTabStop;
    1784           2 :     long x = nCurPos / nDefTab + 1;
    1785           2 :     aTabStop.GetTabPos() = nDefTab * x;
    1786           2 :     return aTabStop;
    1787             : }
    1788             : 
    1789      324907 : void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS )
    1790             : {
    1791      324907 :     sal_Bool bStyleChanged = ( pStyle != pS );
    1792      324907 :     pStyle = pS;
    1793             :     // Only when other style sheet, not when current style sheet modified
    1794      324907 :     if ( pStyle && bStyleChanged )
    1795             :     {
    1796             :         // Selectively remove the attributes from the paragraph formatting
    1797             :         // which are specified in the style, so that the attributes of the
    1798             :         // style can have an affect.
    1799      101651 :         const SfxItemSet& rStyleAttribs = pStyle->GetItemSet();
    1800     4980899 :         for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
    1801             :         {
    1802             :             // Don't change bullet on/off
    1803     4879248 :             if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON ) )
    1804     3052277 :                 aAttribSet.ClearItem( nWhich );
    1805             :         }
    1806             :     }
    1807      324907 : }
    1808             : 
    1809     6770032 : const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich ) const
    1810             : {
    1811             :     // Hard paragraph attributes take precedence!
    1812     6770032 :     const SfxItemSet* pTakeFrom = &aAttribSet;
    1813     6770032 :     if ( pStyle && ( aAttribSet.GetItemState( nWhich, sal_False ) != SFX_ITEM_ON  ) )
    1814      934065 :         pTakeFrom = &pStyle->GetItemSet();
    1815             : 
    1816     6770032 :     return pTakeFrom->Get( nWhich );
    1817             : }
    1818             : 
    1819        6749 : bool ContentAttribs::HasItem( sal_uInt16 nWhich ) const
    1820             : {
    1821        6749 :     bool bHasItem = false;
    1822        6749 :     if ( aAttribSet.GetItemState( nWhich, sal_False ) == SFX_ITEM_ON  )
    1823           0 :         bHasItem = true;
    1824        6749 :     else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SFX_ITEM_ON )
    1825           0 :         bHasItem = true;
    1826             : 
    1827        6749 :     return bHasItem;
    1828             : }
    1829             : 
    1830             : 
    1831           0 : ItemList::ItemList() : CurrentItem( 0 )
    1832             : {
    1833           0 : }
    1834             : 
    1835           0 : const SfxPoolItem* ItemList::First()
    1836             : {
    1837           0 :     CurrentItem = 0;
    1838           0 :     return aItemPool.empty() ? NULL : aItemPool[ 0 ];
    1839             : }
    1840             : 
    1841           0 : const SfxPoolItem* ItemList::Next()
    1842             : {
    1843           0 :     if ( CurrentItem + 1 < aItemPool.size() )
    1844             :     {
    1845           0 :         ++CurrentItem;
    1846           0 :         return aItemPool[ CurrentItem ];
    1847             :     }
    1848           0 :     return NULL;
    1849             : }
    1850             : 
    1851           0 : void ItemList::Insert( const SfxPoolItem* pItem )
    1852             : {
    1853           0 :     aItemPool.push_back( pItem );
    1854           0 :     CurrentItem = aItemPool.size() - 1;
    1855           0 : }
    1856             : 
    1857             : 
    1858       19585 : EditDoc::EditDoc( SfxItemPool* pPool ) :
    1859             :     nLastCache(0),
    1860           7 :     pItemPool(pPool ? pPool : new EditEngineItemPool(false)),
    1861             :     nDefTab(DEFTAB),
    1862             :     bIsVertical(false),
    1863             :     bIsFixedCellHeight(false),
    1864             :     bOwnerOfPool(pPool ? false : true),
    1865       19592 :     bModified(false)
    1866             : {
    1867             :     // Don't create a empty node, Clear() will be called in EditEngine-CTOR
    1868       19585 : };
    1869             : 
    1870       39052 : EditDoc::~EditDoc()
    1871             : {
    1872       19526 :     ImplDestroyContents();
    1873       19526 :     if ( bOwnerOfPool )
    1874           7 :         SfxItemPool::Free(pItemPool);
    1875       19526 : }
    1876             : 
    1877             : namespace {
    1878             : 
    1879             : class RemoveEachItemFromPool : std::unary_function<ContentNode, void>
    1880             : {
    1881             :     EditDoc& mrDoc;
    1882             : public:
    1883      479835 :     RemoveEachItemFromPool(EditDoc& rDoc) : mrDoc(rDoc) {}
    1884      465787 :     void operator() (const ContentNode& rNode)
    1885             :     {
    1886      465787 :         mrDoc.RemoveItemsFromPool(rNode);
    1887      465787 :     }
    1888             : };
    1889             : 
    1890             : }
    1891             : 
    1892      479835 : void EditDoc::ImplDestroyContents()
    1893             : {
    1894      479835 :     std::for_each(maContents.begin(), maContents.end(), RemoveEachItemFromPool(*this));
    1895      479835 :     maContents.clear();
    1896      479835 : }
    1897             : 
    1898      466330 : void EditDoc::RemoveItemsFromPool(const ContentNode& rNode)
    1899             : {
    1900     1545446 :     for (size_t nAttr = 0; nAttr < rNode.GetCharAttribs().Count(); ++nAttr)
    1901             :     {
    1902     1079116 :         const EditCharAttrib& rAttr = rNode.GetCharAttribs().GetAttribs()[nAttr];
    1903     1079116 :         GetItemPool().Remove(*rAttr.GetItem());
    1904             :     }
    1905      466330 : }
    1906             : 
    1907     1022655 : void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, short nScriptType )
    1908             : {
    1909     1022655 :     Font aPrevFont( rFont );
    1910     1022655 :     rFont.SetAlign( ALIGN_BASELINE );
    1911     1022655 :     rFont.SetTransparent( sal_True );
    1912             : 
    1913     1022655 :     sal_uInt16 nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType );
    1914     1022655 :     sal_uInt16 nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType );
    1915     1022655 :     sal_uInt16 nWhich_FontHeight = GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType );
    1916     1022655 :     sal_uInt16 nWhich_Weight = GetScriptItemId( EE_CHAR_WEIGHT, nScriptType );
    1917     1022655 :     sal_uInt16 nWhich_Italic = GetScriptItemId( EE_CHAR_ITALIC, nScriptType );
    1918             : 
    1919     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontInfo ) == SFX_ITEM_ON ) )
    1920             :     {
    1921      817921 :         const SvxFontItem& rFontItem = (const SvxFontItem&)rSet.Get( nWhich_FontInfo );
    1922      817921 :         rFont.SetName( rFontItem.GetFamilyName() );
    1923      817921 :         rFont.SetFamily( rFontItem.GetFamily() );
    1924      817921 :         rFont.SetPitch( rFontItem.GetPitch() );
    1925      817921 :         rFont.SetCharSet( rFontItem.GetCharSet() );
    1926             :     }
    1927     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( nWhich_Language ) == SFX_ITEM_ON ) )
    1928      817807 :         rFont.SetLanguage( ((const SvxLanguageItem&)rSet.Get( nWhich_Language )).GetLanguage() );
    1929     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SFX_ITEM_ON ) )
    1930      817771 :         rFont.SetColor( ((const SvxColorItem&)rSet.Get( EE_CHAR_COLOR )).GetValue() );
    1931     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SFX_ITEM_ON ) )
    1932      819587 :         rFont.SetSize( Size( rFont.GetSize().Width(), ((const SvxFontHeightItem&)rSet.Get( nWhich_FontHeight ) ).GetHeight() ) );
    1933     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SFX_ITEM_ON ) )
    1934      817814 :         rFont.SetWeight( ((const SvxWeightItem&)rSet.Get( nWhich_Weight )).GetWeight() );
    1935     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_UNDERLINE ) == SFX_ITEM_ON ) )
    1936      817815 :         rFont.SetUnderline( ((const SvxUnderlineItem&)rSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() );
    1937     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OVERLINE ) == SFX_ITEM_ON ) )
    1938      817833 :         rFont.SetOverline( ((const SvxOverlineItem&)rSet.Get( EE_CHAR_OVERLINE )).GetLineStyle() );
    1939     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_STRIKEOUT ) == SFX_ITEM_ON ) )
    1940      817880 :         rFont.SetStrikeout( ((const SvxCrossedOutItem&)rSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() );
    1941     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( nWhich_Italic ) == SFX_ITEM_ON ) )
    1942      817848 :         rFont.SetItalic( ((const SvxPostureItem&)rSet.Get( nWhich_Italic )).GetPosture() );
    1943     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OUTLINE ) == SFX_ITEM_ON ) )
    1944      817788 :         rFont.SetOutline( ((const SvxContourItem&)rSet.Get( EE_CHAR_OUTLINE )).GetValue() );
    1945     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_SHADOW ) == SFX_ITEM_ON ) )
    1946      817842 :         rFont.SetShadow( ((const SvxShadowedItem&)rSet.Get( EE_CHAR_SHADOW )).GetValue() );
    1947     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_ESCAPEMENT ) == SFX_ITEM_ON ) )
    1948             :     {
    1949      817947 :         const SvxEscapementItem& rEsc = (const SvxEscapementItem&) rSet.Get( EE_CHAR_ESCAPEMENT );
    1950             : 
    1951      817947 :         sal_uInt16 nProp = rEsc.GetProp();
    1952      817947 :         rFont.SetPropr( (sal_uInt8)nProp );
    1953             : 
    1954      817947 :         short nEsc = rEsc.GetEsc();
    1955      817947 :         if ( nEsc == DFLT_ESC_AUTO_SUPER )
    1956           0 :             nEsc = 100 - nProp;
    1957      817947 :         else if ( nEsc == DFLT_ESC_AUTO_SUB )
    1958           0 :             nEsc = sal::static_int_cast< short >( -( 100 - nProp ) );
    1959      817947 :         rFont.SetEscapement( nEsc );
    1960             :     }
    1961     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_PAIRKERNING ) == SFX_ITEM_ON ) )
    1962      817895 :         rFont.SetKerning( ((const SvxAutoKernItem&)rSet.Get( EE_CHAR_PAIRKERNING )).GetValue() );
    1963     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_KERNING ) == SFX_ITEM_ON ) )
    1964      817845 :         rFont.SetFixKerning( ((const SvxKerningItem&)rSet.Get( EE_CHAR_KERNING )).GetValue() );
    1965     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_WLM ) == SFX_ITEM_ON ) )
    1966      817915 :         rFont.SetWordLineMode( ((const SvxWordLineModeItem&)rSet.Get( EE_CHAR_WLM )).GetValue() );
    1967     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_EMPHASISMARK ) == SFX_ITEM_ON ) )
    1968      817839 :         rFont.SetEmphasisMark( ((const SvxEmphasisMarkItem&)rSet.Get( EE_CHAR_EMPHASISMARK )).GetValue() );
    1969     1022655 :     if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_RELIEF ) == SFX_ITEM_ON ) )
    1970      817602 :         rFont.SetRelief( (FontRelief)((const SvxCharReliefItem&)rSet.Get( EE_CHAR_RELIEF )).GetValue() );
    1971             : 
    1972             :     // If comparing the entire font, or if checking before each alteration
    1973             :     // whether the value changes, remains relatively the same thing.
    1974             :     // So possible one MakeUniqFont more in the font, but as a result a quicker
    1975             :     // abortion of the query, or one must each time check bChanged.
    1976     1022655 :     if ( rFont == aPrevFont  )
    1977      835142 :         rFont = aPrevFont;  // => The same ImpPointer for IsSameInstance
    1978     1022655 : }
    1979             : 
    1980      237053 : void EditDoc::CreateDefFont( sal_Bool bUseStyles )
    1981             : {
    1982      237053 :     SfxItemSet aTmpSet( GetItemPool(), EE_PARA_START, EE_CHAR_END );
    1983      237053 :     CreateFont( aDefFont, aTmpSet );
    1984      237053 :     aDefFont.SetVertical( IsVertical() );
    1985      237053 :     aDefFont.SetOrientation( IsVertical() ? 2700 : 0 );
    1986             : 
    1987      474106 :     for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ )
    1988             :     {
    1989      237053 :         ContentNode* pNode = GetObject( nNode );
    1990      237053 :         pNode->GetCharAttribs().GetDefFont() = aDefFont;
    1991      237053 :         if ( bUseStyles )
    1992           0 :             pNode->CreateDefFont();
    1993      237053 :     }
    1994      237053 : }
    1995             : 
    1996             : static const sal_Unicode aCR[] = { 0x0d, 0x00 };
    1997             : static const sal_Unicode aLF[] = { 0x0a, 0x00 };
    1998             : static const sal_Unicode aCRLF[] = { 0x0d, 0x0a, 0x00 };
    1999             : 
    2000     3783495 : sal_Int32 EditDoc::GetPos(const ContentNode* p) const
    2001             : {
    2002     3783495 :     return FastGetPos(maContents, p, nLastCache);
    2003             : }
    2004             : 
    2005     3658360 : const ContentNode* EditDoc::GetObject(sal_Int32 nPos) const
    2006             : {
    2007     3658360 :     return 0 <= nPos && static_cast<size_t>(nPos) < maContents.size() ? &maContents[nPos] : NULL;
    2008             : }
    2009             : 
    2010     3219632 : ContentNode* EditDoc::GetObject(sal_Int32 nPos)
    2011             : {
    2012     3219632 :     return 0 <= nPos && static_cast<size_t>(nPos) < maContents.size() ? &maContents[nPos] : NULL;
    2013             : }
    2014             : 
    2015           0 : const ContentNode* EditDoc::operator[](sal_Int32 nPos) const
    2016             : {
    2017           0 :     return GetObject(nPos);
    2018             : }
    2019             : 
    2020      788248 : ContentNode* EditDoc::operator[](sal_Int32 nPos)
    2021             : {
    2022      788248 :     return GetObject(nPos);
    2023             : }
    2024             : 
    2025      466395 : void EditDoc::Insert(sal_Int32 nPos, ContentNode* p)
    2026             : {
    2027      466395 :     if (nPos < 0 || nPos == SAL_MAX_INT32)
    2028             :     {
    2029             :         SAL_WARN( "editeng", "EditDoc::Insert - overflow pos " << nPos);
    2030      466395 :         return;
    2031             :     }
    2032      466395 :     maContents.insert(maContents.begin()+nPos, p);
    2033             : }
    2034             : 
    2035         543 : void EditDoc::Remove(sal_Int32 nPos)
    2036             : {
    2037         543 :     if (nPos < 0 || static_cast<size_t>(nPos) >= maContents.size())
    2038             :     {
    2039             :         SAL_WARN( "editeng", "EditDoc::Remove - out of bounds pos " << nPos);
    2040         543 :         return;
    2041             :     }
    2042         543 :     maContents.erase(maContents.begin() + nPos);
    2043             : }
    2044             : 
    2045           6 : void EditDoc::Release(sal_Int32 nPos)
    2046             : {
    2047           6 :     if (nPos < 0 || static_cast<size_t>(nPos) >= maContents.size())
    2048             :     {
    2049             :         SAL_WARN( "editeng", "EditDoc::Release - out of bounds pos " << nPos);
    2050           6 :         return;
    2051             :     }
    2052           6 :     maContents.release(maContents.begin() + nPos).release();
    2053             : }
    2054             : 
    2055     1065368 : sal_Int32 EditDoc::Count() const
    2056             : {
    2057     1065368 :     size_t nSize = maContents.size();
    2058     1065368 :     if (nSize > SAL_MAX_INT32)
    2059             :     {
    2060             :         SAL_WARN( "editeng", "EditDoc::Count - overflow " << nSize);
    2061           0 :         return SAL_MAX_INT32;
    2062             :     }
    2063     1065368 :     return static_cast<sal_Int32>(nSize);
    2064             : }
    2065             : 
    2066        6846 : OUString EditDoc::GetSepStr( LineEnd eEnd )
    2067             : {
    2068        6846 :     OUString aSep;
    2069        6846 :     if ( eEnd == LINEEND_CR )
    2070           0 :         aSep = aCR;
    2071        6846 :     else if ( eEnd == LINEEND_LF )
    2072        6846 :         aSep = aLF;
    2073             :     else
    2074           0 :         aSep = aCRLF;
    2075        6846 :     return aSep;
    2076             : }
    2077             : 
    2078        1509 : XubString EditDoc::GetText( LineEnd eEnd ) const
    2079             : {
    2080        1509 :     sal_uLong nLen = GetTextLen();
    2081        1509 :     sal_Int32 nNodes = Count();
    2082        1509 :     if (nNodes == 0)
    2083           0 :         return OUString();
    2084             : 
    2085        1509 :     OUString aSep = EditDoc::GetSepStr( eEnd );
    2086        1509 :     sal_Int32 nSepSize = aSep.getLength();
    2087             : 
    2088        1509 :     if ( nSepSize )
    2089        1509 :         nLen += (nNodes - 1) * nSepSize;
    2090             : 
    2091        1509 :     rtl_uString* newStr = rtl_uString_alloc(nLen);
    2092        1509 :     sal_Unicode* pCur = newStr->buffer;
    2093        1509 :     sal_Int32 nLastNode = nNodes-1;
    2094        3019 :     for ( sal_Int32 nNode = 0; nNode < nNodes; nNode++ )
    2095             :     {
    2096        1510 :         String aTmp( GetParaAsString( GetObject(nNode) ) );
    2097        1510 :         memcpy( pCur, aTmp.GetBuffer(), aTmp.Len()*sizeof(sal_Unicode) );
    2098        1510 :         pCur += aTmp.Len();
    2099        1510 :         if ( nSepSize && ( nNode != nLastNode ) )
    2100             :         {
    2101           1 :             memcpy( pCur, aSep.getStr(), nSepSize*sizeof(sal_Unicode ) );
    2102           1 :             pCur += nSepSize;
    2103             :         }
    2104        1510 :     }
    2105             :     assert(pCur - newStr->buffer == newStr->length);
    2106        1509 :     return OUString(newStr, SAL_NO_ACQUIRE);
    2107             : }
    2108             : 
    2109       15966 : XubString EditDoc::GetParaAsString( sal_Int32 nNode ) const
    2110             : {
    2111       15966 :     return GetParaAsString( GetObject( nNode ) );
    2112             : }
    2113             : 
    2114       22897 : XubString EditDoc::GetParaAsString(
    2115             :     const ContentNode* pNode, sal_uInt16 nStartPos, sal_uInt16 nEndPos, bool bResolveFields) const
    2116             : {
    2117       22897 :     if ( nEndPos > pNode->Len() )
    2118       17476 :         nEndPos = pNode->Len();
    2119             : 
    2120             :     DBG_ASSERT( nStartPos <= nEndPos, "Start and End reversed?" );
    2121             : 
    2122       22897 :     sal_uInt16 nIndex = nStartPos;
    2123       22897 :     XubString aStr;
    2124       22897 :     const EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature( nIndex );
    2125       55407 :     while ( nIndex < nEndPos )
    2126             :     {
    2127        9613 :         sal_uInt16 nEnd = nEndPos;
    2128        9613 :         if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) )
    2129         220 :             nEnd = pNextFeature->GetStart();
    2130             :         else
    2131        9393 :             pNextFeature = 0;   // Feature does not interest the below
    2132             : 
    2133             :         DBG_ASSERT( nEnd >= nIndex, "End in front of the index?" );
    2134             :         //!! beware of sub string length  of -1 which is also defined as STRING_LEN and
    2135             :         //!! thus would result in adding the whole sub string up to the end of the node !!
    2136        9613 :         if (nEnd > nIndex)
    2137        9438 :             aStr += XubString(pNode->GetString(), nIndex, nEnd - nIndex);
    2138             : 
    2139        9613 :         if ( pNextFeature )
    2140             :         {
    2141         220 :             switch ( pNextFeature->GetItem()->Which() )
    2142             :             {
    2143           0 :                 case EE_FEATURE_TAB:    aStr += '\t';
    2144           0 :                 break;
    2145           9 :                 case EE_FEATURE_LINEBR: aStr += '\x0A';
    2146           9 :                 break;
    2147             :                 case EE_FEATURE_FIELD:
    2148         211 :                     if ( bResolveFields )
    2149         211 :                         aStr += static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue();
    2150         211 :                 break;
    2151             :                 default:    OSL_FAIL( "What feature?" );
    2152             :             }
    2153         220 :             pNextFeature = pNode->GetCharAttribs().FindFeature( ++nEnd );
    2154             :         }
    2155        9613 :         nIndex = nEnd;
    2156             :     }
    2157       22897 :     return aStr;
    2158             : }
    2159             : 
    2160      882874 : EditPaM EditDoc::GetStartPaM() const
    2161             : {
    2162      882874 :     ContentNode* p = const_cast<ContentNode*>(GetObject(0));
    2163      882874 :     return EditPaM(p, 0);
    2164             : }
    2165             : 
    2166        7280 : EditPaM EditDoc::GetEndPaM() const
    2167             : {
    2168        7280 :     ContentNode* pLastNode = const_cast<ContentNode*>(GetObject(Count()-1));
    2169        7280 :     return EditPaM( pLastNode, pLastNode->Len() );
    2170             : }
    2171             : 
    2172        1523 : sal_uLong EditDoc::GetTextLen() const
    2173             : {
    2174        1523 :     sal_uLong nLen = 0;
    2175        3047 :     for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ )
    2176             :     {
    2177        1524 :         const ContentNode* pNode = GetObject( nNode );
    2178        1524 :         nLen += pNode->Len();
    2179             :         // Fields can be longer than the placeholder in the Node
    2180        1524 :         const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
    2181       13407 :         for (size_t nAttr = rAttrs.size(); nAttr; )
    2182             :         {
    2183       10359 :             const EditCharAttrib& rAttr = rAttrs[--nAttr];
    2184       10359 :             if (rAttr.Which() == EE_FEATURE_FIELD)
    2185             :             {
    2186           0 :                 sal_Int32 nFieldLen = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength();
    2187           0 :                 if ( !nFieldLen )
    2188           0 :                     nLen--;
    2189             :                 else
    2190           0 :                     nLen += nFieldLen-1;
    2191             :             }
    2192             :         }
    2193             :     }
    2194        1523 :     return nLen;
    2195             : }
    2196             : 
    2197      237053 : EditPaM EditDoc::Clear()
    2198             : {
    2199      237053 :     ImplDestroyContents();
    2200             : 
    2201      237053 :     ContentNode* pNode = new ContentNode( GetItemPool() );
    2202      237053 :     Insert(0, pNode);
    2203             : 
    2204      237053 :     CreateDefFont(false);
    2205             : 
    2206      237053 :     SetModified(false);
    2207             : 
    2208      237053 :     EditPaM aPaM( pNode, 0 );
    2209      237053 :     return aPaM;
    2210             : }
    2211             : 
    2212     1340506 : void EditDoc::SetModified( bool b )
    2213             : {
    2214     1340506 :     bModified = b;
    2215     1340506 :     if ( bModified )
    2216             :     {
    2217     1103410 :         aModifyHdl.Call( NULL );
    2218             :     }
    2219     1340506 : }
    2220             : 
    2221      223256 : EditPaM EditDoc::RemoveText()
    2222             : {
    2223             :     // Keep the old ItemSet, to keep the chart Font.
    2224      223256 :     ContentNode* pPrevFirstNode = GetObject(0);
    2225      223256 :     SfxStyleSheet* pPrevStyle = pPrevFirstNode->GetStyleSheet();
    2226      223256 :     SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() );
    2227      446512 :     Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() );
    2228             : 
    2229      223256 :     ImplDestroyContents();
    2230             : 
    2231      223256 :     ContentNode* pNode = new ContentNode( GetItemPool() );
    2232      223256 :     Insert(0, pNode);
    2233             : 
    2234      223256 :     pNode->SetStyleSheet(pPrevStyle, false);
    2235      223256 :     pNode->GetContentAttribs().GetItems().Set( aPrevSet );
    2236      223256 :     pNode->GetCharAttribs().GetDefFont() = aPrevFont;
    2237             : 
    2238      223256 :     SetModified(true);
    2239             : 
    2240      223256 :     EditPaM aPaM( pNode, 0 );
    2241      446512 :     return aPaM;
    2242             : }
    2243             : 
    2244      238524 : EditPaM EditDoc::InsertText( EditPaM aPaM, const XubString& rStr )
    2245             : {
    2246             :     DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "EditDoc::InsertText: Newlines prohibited in paragraph!" );
    2247             :     DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "EditDoc::InsertText: Newlines prohibited in paragraph!" );
    2248             :     DBG_ASSERT( rStr.Search( '\t' ) == STRING_NOTFOUND, "EditDoc::InsertText: Newlines prohibited in paragraph!" );
    2249             :     DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertText1" );
    2250             : 
    2251      238524 :     aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() );
    2252      238524 :     aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.Len(), GetItemPool() );
    2253      238524 :     aPaM.GetIndex() = aPaM.GetIndex() + rStr.Len();
    2254             : 
    2255      238524 :     SetModified( sal_True );
    2256             : 
    2257      238524 :     return aPaM;
    2258             : }
    2259             : 
    2260        1315 : EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, sal_Bool bKeepEndingAttribs )
    2261             : {
    2262             :     DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertParaBreak" );
    2263        1315 :     ContentNode* pCurNode = aPaM.GetNode();
    2264        1315 :     sal_Int32 nPos = GetPos( pCurNode );
    2265        1315 :     XubString aStr = aPaM.GetNode()->Copy( aPaM.GetIndex() );
    2266        1315 :     aPaM.GetNode()->Erase( aPaM.GetIndex() );
    2267             : 
    2268             :     // the paragraph attributes...
    2269        2630 :     ContentAttribs aContentAttribs( aPaM.GetNode()->GetContentAttribs() );
    2270             : 
    2271             :     // for a new paragraph we like to have the bullet/numbering visible by default
    2272        1315 :     aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, sal_True), EE_PARA_BULLETSTATE );
    2273             : 
    2274             :     // ContenNode constructor copies also the paragraph attributes
    2275        1315 :     ContentNode* pNode = new ContentNode( aStr, aContentAttribs );
    2276             : 
    2277             :     // Copy the Default Font
    2278        1315 :     pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont();
    2279        1315 :     SfxStyleSheet* pStyle = aPaM.GetNode()->GetStyleSheet();
    2280        1315 :     if ( pStyle )
    2281             :     {
    2282         705 :         XubString aFollow( pStyle->GetFollow() );
    2283         705 :         if ( aFollow.Len() && ( aFollow != pStyle->GetName() ) )
    2284             :         {
    2285           0 :             SfxStyleSheetBase* pNext = pStyle->GetPool().Find( aFollow, pStyle->GetFamily() );
    2286           0 :             pNode->SetStyleSheet( (SfxStyleSheet*)pNext );
    2287         705 :         }
    2288             :     }
    2289             : 
    2290             :     // Character attributes may need to be copied or trimmed:
    2291        1315 :     pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs );
    2292             : 
    2293        1315 :     Insert(nPos+1, pNode);
    2294             : 
    2295        1315 :     SetModified(true);
    2296             : 
    2297        1315 :     aPaM.SetNode( pNode );
    2298        1315 :     aPaM.SetIndex( 0 );
    2299        2630 :     return aPaM;
    2300             : }
    2301             : 
    2302        3689 : EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem  )
    2303             : {
    2304             :     DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertFeature" );
    2305             : 
    2306        3689 :     aPaM.GetNode()->Insert( OUString(CH_FEATURE), aPaM.GetIndex() );
    2307        3689 :     aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() );
    2308             : 
    2309             :     // Create a feature-attribute for the feature...
    2310        3689 :     EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 );
    2311             :     DBG_ASSERT( pAttrib, "Why can not the feature be created?" );
    2312        3689 :     aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttrib );
    2313             : 
    2314        3689 :     SetModified( sal_True );
    2315             : 
    2316        3689 :     aPaM.GetIndex()++;
    2317        3689 :     return aPaM;
    2318             : }
    2319             : 
    2320         543 : EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight )
    2321             : {
    2322         543 :     const EditPaM aPaM( pLeft, pLeft->Len() );
    2323             : 
    2324             :     // First the attributes, otherwise nLen will not be correct!
    2325         543 :     pLeft->AppendAttribs( pRight );
    2326             :     // then the Text...
    2327         543 :     pLeft->Append(pRight->GetString());
    2328             : 
    2329             :     // the one to the right disappears.
    2330         543 :     RemoveItemsFromPool(*pRight);
    2331         543 :     sal_Int32 nRight = GetPos( pRight );
    2332         543 :     Remove( nRight );
    2333             : 
    2334         543 :     SetModified(true);
    2335             : 
    2336         543 :     return aPaM;
    2337             : }
    2338             : 
    2339        1268 : EditPaM EditDoc::RemoveChars( EditPaM aPaM, sal_uInt16 nChars )
    2340             : {
    2341             :     // Maybe remove Features!
    2342        1268 :     aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars );
    2343        1268 :     aPaM.GetNode()->CollapsAttribs( aPaM.GetIndex(), nChars, GetItemPool() );
    2344             : 
    2345        1268 :     SetModified( sal_True );
    2346             : 
    2347        1268 :     return aPaM;
    2348             : }
    2349             : 
    2350       15941 : void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, const SfxPoolItem& rPoolItem )
    2351             : {
    2352             :     DBG_ASSERT( pNode, "What to do with the attribute?" );
    2353             :     DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribute to large!" );
    2354             : 
    2355             :     // for Optimization:
    2356             :     // This ends at the beginning of the selection => can be expanded
    2357       15941 :     EditCharAttrib* pEndingAttrib = 0;
    2358             :     // This starts at the end of the selection => can be expanded
    2359       15941 :     EditCharAttrib* pStartingAttrib = 0;
    2360             : 
    2361             :     DBG_ASSERT( nStart <= nEnd, "Small miscalculations in InsertAttribInSelection" );
    2362             : 
    2363       15941 :     RemoveAttribs( pNode, nStart, nEnd, pStartingAttrib, pEndingAttrib, rPoolItem.Which() );
    2364             : 
    2365       16005 :     if ( pStartingAttrib && pEndingAttrib &&
    2366       15943 :          ( *(pStartingAttrib->GetItem()) == rPoolItem ) &&
    2367           0 :          ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
    2368             :     {
    2369             :         // Will become a large Attribute.
    2370           0 :         pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd();
    2371           0 :         GetItemPool().Remove( *(pStartingAttrib->GetItem()) );
    2372           0 :         pNode->GetCharAttribs().Remove(pStartingAttrib);
    2373             :     }
    2374       15941 :     else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) )
    2375          59 :         pStartingAttrib->GetStart() = nStart;
    2376       15882 :     else if ( pEndingAttrib && ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
    2377        4027 :         pEndingAttrib->GetEnd() = nEnd;
    2378             :     else
    2379       11855 :         InsertAttrib( rPoolItem, pNode, nStart, nEnd );
    2380             : 
    2381       15941 :     if ( pStartingAttrib )
    2382          62 :         pNode->GetCharAttribs().ResortAttribs();
    2383             : 
    2384       15941 :     SetModified(true);
    2385       15941 : }
    2386             : 
    2387          82 : sal_Bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, sal_uInt16 nWhich )
    2388             : {
    2389             :     EditCharAttrib* pStarting;
    2390             :     EditCharAttrib* pEnding;
    2391          82 :     return RemoveAttribs( pNode, nStart, nEnd, pStarting, pEnding, nWhich );
    2392             : }
    2393             : 
    2394       16023 : sal_Bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, sal_uInt16 nWhich )
    2395             : {
    2396             : 
    2397             :     DBG_ASSERT( pNode, "What to do with the attribute?" );
    2398             :     DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribute to large!" );
    2399             : 
    2400             :     // This ends at the beginning of the selection => can be expanded
    2401       16023 :     rpEnding = 0;
    2402             :     // This starts at the end of the selection => can be expanded
    2403       16023 :     rpStarting = 0;
    2404             : 
    2405       16023 :     bool bChanged = false;
    2406             : 
    2407             :     DBG_ASSERT( nStart <= nEnd, "Small miscalculations in InsertAttribInSelection" );
    2408             : 
    2409             :     // iterate over the attributes ...
    2410       16023 :     size_t nAttr = 0;
    2411       16023 :     CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs();
    2412       16023 :     EditCharAttrib* pAttr = GetAttrib(rAttribs, nAttr);
    2413      178941 :     while ( pAttr )
    2414             :     {
    2415      147006 :         bool bRemoveAttrib = false;
    2416      147006 :         sal_uInt16 nAttrWhich = pAttr->Which();
    2417      147006 :         if ( ( nAttrWhich < EE_FEATURE_START ) && ( !nWhich || ( nAttrWhich == nWhich ) ) )
    2418             :         {
    2419             :             // Attribute starts in Selection
    2420        6684 :             if ( ( pAttr->GetStart() >= nStart ) && ( pAttr->GetStart() <= nEnd ) )
    2421             :             {
    2422        1116 :                 bChanged = sal_True;
    2423        1116 :                 if ( pAttr->GetEnd() > nEnd )
    2424             :                 {
    2425          62 :                     pAttr->GetStart() = nEnd;   // then it starts after this
    2426          62 :                     rpStarting = pAttr;
    2427          62 :                     if ( nWhich )
    2428          62 :                         break;  // There can be no further attributes here
    2429             :                 }
    2430        1054 :                 else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
    2431             :                 {
    2432             :                     // Delete feature only if on the exact spot
    2433        1054 :                     bRemoveAttrib = sal_True;
    2434             :                 }
    2435             :             }
    2436             : 
    2437             :             // Attribute ends in Selection
    2438        5568 :             else if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetEnd() <= nEnd ) )
    2439             :             {
    2440        4410 :                 bChanged = sal_True;
    2441        4410 :                 if ( ( pAttr->GetStart() < nStart ) && !pAttr->IsFeature() )
    2442             :                 {
    2443        4410 :                     pAttr->GetEnd() = nStart;   // then it ends here
    2444        4410 :                     rpEnding = pAttr;
    2445             :                 }
    2446           0 :                 else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
    2447             :                 {
    2448             :                     // Delete feature only if on the exact spot
    2449           0 :                     bRemoveAttrib = sal_True;
    2450             :                 }
    2451             :             }
    2452             :             // Attribute overlaps the selection
    2453        1158 :             else if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) )
    2454             :             {
    2455          49 :                 bChanged = sal_True;
    2456          49 :                 if ( pAttr->GetStart() == nStart )
    2457             :                 {
    2458           0 :                     pAttr->GetStart() = nEnd;
    2459           0 :                     rpStarting = pAttr;
    2460           0 :                     if ( nWhich )
    2461           0 :                         break;  // There can be further attributes!
    2462             :                 }
    2463          49 :                 else if ( pAttr->GetEnd() == nEnd )
    2464             :                 {
    2465           0 :                     pAttr->GetEnd() = nStart;
    2466           0 :                     rpEnding = pAttr;
    2467           0 :                     if ( nWhich )
    2468           0 :                         break;  // There can be further attributes!
    2469             :                 }
    2470             :                 else // Attribute must be split ...
    2471             :                 {
    2472          49 :                     sal_uInt16 nOldEnd = pAttr->GetEnd();
    2473          49 :                     pAttr->GetEnd() = nStart;
    2474          49 :                     rpEnding = pAttr;
    2475          49 :                     InsertAttrib( *pAttr->GetItem(), pNode, nEnd, nOldEnd );
    2476          49 :                     if ( nWhich )
    2477          49 :                         break;  // There can be further attributes!
    2478             :                 }
    2479             :             }
    2480             :         }
    2481      146895 :         if ( bRemoveAttrib )
    2482             :         {
    2483             :             DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Delete and retain the same attribute?" );
    2484             :             DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" );
    2485        1054 :             GetItemPool().Remove( *pAttr->GetItem() );
    2486        1054 :             rAttribs.erase(rAttribs.begin()+nAttr);
    2487        1054 :             nAttr--;
    2488             :         }
    2489      146895 :         nAttr++;
    2490      146895 :         pAttr = GetAttrib(rAttribs, nAttr);
    2491             :     }
    2492             : 
    2493       16023 :     if ( bChanged )
    2494             :     {
    2495             :         // char attributes need to be sorted by start again
    2496        5550 :         pNode->GetCharAttribs().ResortAttribs();
    2497        5550 :         SetModified(true);
    2498             :     }
    2499             : 
    2500       16023 :     return bChanged;
    2501             : }
    2502             : 
    2503       15802 : void EditDoc::InsertAttrib( const SfxPoolItem& rPoolItem, ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd )
    2504             : {
    2505             :     // This method no longer checks whether a corresponding attribute already
    2506             :     // exists at this place!
    2507       15802 :     EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rPoolItem, nStart, nEnd );
    2508             :     DBG_ASSERT( pAttrib, "MakeCharAttrib failed!" );
    2509       15802 :     pNode->GetCharAttribs().InsertAttrib( pAttrib );
    2510             : 
    2511       15802 :     SetModified( sal_True );
    2512       15802 : }
    2513             : 
    2514       20011 : void EditDoc::InsertAttrib( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, const SfxPoolItem& rPoolItem )
    2515             : {
    2516       20011 :     if ( nStart != nEnd )
    2517             :     {
    2518       15941 :         InsertAttribInSelection( pNode, nStart, nEnd, rPoolItem );
    2519             :     }
    2520             :     else
    2521             :     {
    2522             :         // Check whether already a new attribute with WhichId exists at this place:
    2523        4070 :         CharAttribList& rAttrList = pNode->GetCharAttribs();
    2524        4070 :         EditCharAttrib* pAttr = rAttrList.FindEmptyAttrib( rPoolItem.Which(), nStart );
    2525        4070 :         if ( pAttr )
    2526             :         {
    2527             :             // Remove attribute....
    2528        1093 :             rAttrList.Release(pAttr);
    2529             :         }
    2530             : 
    2531             :         // check whether 'the same' attribute exist at this place.
    2532        4070 :         pAttr = rAttrList.FindAttrib( rPoolItem.Which(), nStart );
    2533        4070 :         if ( pAttr )
    2534             :         {
    2535         180 :             if ( pAttr->IsInside( nStart ) )    // split
    2536             :             {
    2537             :                 // check again if really splitting, or return !
    2538           0 :                 sal_uInt16 nOldEnd = pAttr->GetEnd();
    2539           0 :                 pAttr->GetEnd() = nStart;
    2540           0 :                 EditCharAttrib* pNew = MakeCharAttrib( GetItemPool(), *(pAttr->GetItem()), nStart, nOldEnd );
    2541           0 :                 rAttrList.InsertAttrib(pNew);
    2542             :             }
    2543         180 :             else if ( pAttr->GetEnd() == nStart )
    2544             :             {
    2545             :                 DBG_ASSERT( !pAttr->IsEmpty(), "Still an empty attribute?" );
    2546             :                 // Check if exactly the same attribute
    2547         180 :                 if ( *(pAttr->GetItem()) == rPoolItem )
    2548       20183 :                     return;
    2549             :             }
    2550             :         }
    2551        3898 :         InsertAttrib( rPoolItem, pNode, nStart, nStart );
    2552             :     }
    2553             : 
    2554       19839 :     SetModified( sal_True );
    2555             : }
    2556             : 
    2557        2456 : void EditDoc::FindAttribs( ContentNode* pNode, sal_uInt16 nStartPos, sal_uInt16 nEndPos, SfxItemSet& rCurSet )
    2558             : {
    2559             :     DBG_ASSERT( pNode, "Where to search?" );
    2560             :     DBG_ASSERT( nStartPos <= nEndPos, "Invalid region!" );
    2561             : 
    2562        2456 :     sal_uInt16 nAttr = 0;
    2563        2456 :     EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
    2564             :     // No Selection...
    2565        2456 :     if ( nStartPos == nEndPos )
    2566             :     {
    2567        7462 :         while ( pAttr && ( pAttr->GetStart() <= nEndPos) )
    2568             :         {
    2569        3942 :             const SfxPoolItem* pItem = 0;
    2570             :             // Attribute is about...
    2571        3942 :             if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
    2572           0 :                 pItem = pAttr->GetItem();
    2573             :             // Attribute ending here is not empty
    2574        3942 :             else if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
    2575             :             {
    2576           0 :                 if ( !pNode->GetCharAttribs().FindEmptyAttrib( pAttr->GetItem()->Which(), nStartPos ) )
    2577           0 :                     pItem = pAttr->GetItem();
    2578             :             }
    2579             :             // Attribute ending here is empty
    2580        3942 :             else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
    2581             :             {
    2582        3544 :                 pItem = pAttr->GetItem();
    2583             :             }
    2584             :             // Attribute starts here
    2585         398 :             else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
    2586             :             {
    2587         398 :                 if ( nStartPos == 0 )   // special case
    2588         398 :                     pItem = pAttr->GetItem();
    2589             :             }
    2590             : 
    2591        3942 :             if ( pItem )
    2592             :             {
    2593        3942 :                 sal_uInt16 nWhich = pItem->Which();
    2594        3942 :                 if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
    2595             :                 {
    2596         416 :                     rCurSet.Put( *pItem );
    2597             :                 }
    2598        3526 :                 else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
    2599             :                 {
    2600        3526 :                     const SfxPoolItem& rItem = rCurSet.Get( nWhich );
    2601        3526 :                     if ( rItem != *pItem )
    2602             :                     {
    2603           0 :                         rCurSet.InvalidateItem( nWhich );
    2604             :                     }
    2605             :                 }
    2606             :             }
    2607        3942 :             nAttr++;
    2608        3942 :             pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
    2609             :         }
    2610             :     }
    2611             :     else    // Selection
    2612             :     {
    2613       15645 :         while ( pAttr && ( pAttr->GetStart() < nEndPos) )
    2614             :         {
    2615       14253 :             const SfxPoolItem* pItem = 0;
    2616             :             // Attribut is about...
    2617       14253 :             if ( ( pAttr->GetStart() <= nStartPos ) && ( pAttr->GetEnd() >= nEndPos ) )
    2618       14252 :                 pItem = pAttr->GetItem();
    2619             :             // Attribute starts right in the middle ...
    2620           1 :             else if ( pAttr->GetStart() >= nStartPos )
    2621             :             {
    2622             :                 // !!! pItem = pAttr->GetItem();
    2623             :                 // PItem is simply not enough, since one for example in case
    2624             :                 // of Shadow, would never find an unequal item, since such a
    2625             :                 // item represents its presence by absence!
    2626             :                 // If (...)
    2627             :                 // It needs to be examined on exactly the same attribute at the
    2628             :                 // breaki point, which is quite expensive.
    2629             :                 // Since optimazation is done when inserting the  attributes
    2630             :                 // this case does not appear so fast ...
    2631             :                 // So based on the need for speed:
    2632           1 :                 rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
    2633             : 
    2634             :             }
    2635             :             // Attribute ends in the middle of it ...
    2636           0 :             else if ( pAttr->GetEnd() > nStartPos )
    2637             :             {
    2638           0 :                 rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
    2639             :             }
    2640             : 
    2641       14253 :             if ( pItem )
    2642             :             {
    2643       14252 :                 sal_uInt16 nWhich = pItem->Which();
    2644       14252 :                 if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
    2645             :                 {
    2646        7200 :                     rCurSet.Put( *pItem );
    2647             :                 }
    2648        7052 :                 else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
    2649             :                 {
    2650        7052 :                     const SfxPoolItem& rItem = rCurSet.Get( nWhich );
    2651        7052 :                     if ( rItem != *pItem )
    2652             :                     {
    2653           0 :                         rCurSet.InvalidateItem( nWhich );
    2654             :                     }
    2655             :                 }
    2656             :             }
    2657       14253 :             nAttr++;
    2658       14253 :             pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
    2659             :         }
    2660             :     }
    2661        2456 : }
    2662             : 
    2663             : namespace {
    2664             : 
    2665             : struct LessByStart : std::binary_function<EditCharAttrib, EditCharAttrib, bool>
    2666             : {
    2667      213934 :     bool operator() (const EditCharAttrib& left, const EditCharAttrib& right) const
    2668             :     {
    2669      213934 :         return left.GetStart() < right.GetStart();
    2670             :     }
    2671             : };
    2672             : 
    2673             : }
    2674             : 
    2675      466395 : CharAttribList::CharAttribList()
    2676             : {
    2677             :     DBG_CTOR( EE_CharAttribList, 0 );
    2678      466395 :     bHasEmptyAttribs = sal_False;
    2679      466395 : }
    2680             : 
    2681      466336 : CharAttribList::~CharAttribList()
    2682             : {
    2683             :     DBG_DTOR( EE_CharAttribList, 0 );
    2684      466336 : }
    2685             : 
    2686     1082593 : void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib )
    2687             : {
    2688             : // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    2689             : // optimize: binary search?    !
    2690             : // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    2691             : 
    2692             :     // Maybe just simply iterate backwards:
    2693             :     // The most common and critical case: Attributes are already sorted
    2694             :     // (InsertBinTextObject!) binary search would not be optimal here.
    2695             :     // => Would bring something!
    2696             : 
    2697     1082593 :     const sal_uInt16 nStart = pAttrib->GetStart(); // may be better for Comp.Opt.
    2698             : 
    2699     1082593 :     if ( pAttrib->IsEmpty() )
    2700      158403 :         bHasEmptyAttribs = true;
    2701             : 
    2702     7013476 :     for (size_t i = 0, n = aAttribs.size(); i < n; ++i)
    2703             :     {
    2704     5932692 :         const EditCharAttrib& rCurAttrib = aAttribs[i];
    2705     5932692 :         if (rCurAttrib.GetStart() > nStart)
    2706             :         {
    2707        1809 :             aAttribs.insert(aAttribs.begin()+i, pAttrib);
    2708     1084402 :             return;
    2709             :         }
    2710             :     }
    2711             : 
    2712     1080784 :     aAttribs.push_back(pAttrib);
    2713             : }
    2714             : 
    2715        6010 : void CharAttribList::ResortAttribs()
    2716             : {
    2717        6010 :     aAttribs.sort(LessByStart());
    2718        6010 : }
    2719             : 
    2720        9845 : void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool )
    2721             : {
    2722       68054 :     for (size_t i = 0; i < aAttribs.size(); ++i)
    2723             :     {
    2724       58209 :         EditCharAttrib& rAttr = aAttribs[i];
    2725      656154 :         for (size_t nNext = i+1; nNext < aAttribs.size(); ++nNext)
    2726             :         {
    2727      598706 :             EditCharAttrib& rNext = aAttribs[nNext];
    2728      598706 :             if (!rAttr.IsFeature() && rNext.GetStart() == rAttr.GetEnd() && rNext.Which() == rAttr.Which())
    2729             :             {
    2730          74 :                 if (*rNext.GetItem() == *rAttr.GetItem())
    2731             :                 {
    2732          49 :                     rAttr.GetEnd() = rNext.GetEnd();
    2733          49 :                     rItemPool.Remove(*rNext.GetItem());
    2734          49 :                     aAttribs.erase(aAttribs.begin()+nNext);
    2735             :                 }
    2736          74 :                 break;  // only 1 attr with same which can start here.
    2737             :             }
    2738      598632 :             else if (rNext.GetStart() > rAttr.GetEnd())
    2739             :             {
    2740         687 :                 break;
    2741             :             }
    2742             :         }
    2743             :     }
    2744        9845 : }
    2745             : 
    2746     1792290 : size_t CharAttribList::Count() const
    2747             : {
    2748     1792290 :     return aAttribs.size();
    2749             : }
    2750             : 
    2751      129780 : const EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) const
    2752             : {
    2753             :     // Backwards, if one ends where the next starts.
    2754             :     // => The starting one is the valid one ...
    2755      129780 :     AttribsType::const_reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend();
    2756      248196 :     for (; it != itEnd; ++it)
    2757             :     {
    2758      126784 :         const EditCharAttrib& rAttr = *it;
    2759      126784 :         if (rAttr.Which() == nWhich && rAttr.IsIn(nPos))
    2760        8368 :             return &rAttr;
    2761             :     }
    2762      121412 :     return NULL;
    2763             : }
    2764             : 
    2765       11789 : EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos )
    2766             : {
    2767             :     // Backwards, if one ends where the next starts.
    2768             :     // => The starting one is the valid one ...
    2769       11789 :     AttribsType::reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend();
    2770       66842 :     for (; it != itEnd; ++it)
    2771             :     {
    2772       55384 :         EditCharAttrib& rAttr = *it;
    2773       55384 :         if (rAttr.Which() == nWhich && rAttr.IsIn(nPos))
    2774         331 :             return &rAttr;
    2775             :     }
    2776       11458 :     return NULL;
    2777             : }
    2778             : 
    2779      182017 : const EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_uInt16 nFromPos ) const
    2780             : {
    2781             :     DBG_ASSERT( nWhich, "FindNextAttrib: Which?" );
    2782      182017 :     AttribsType::const_iterator it = aAttribs.begin(), itEnd = aAttribs.end();
    2783     1134436 :     for (; it != itEnd; ++it)
    2784             :     {
    2785      960604 :         const EditCharAttrib& rAttr = *it;
    2786      960604 :         if (rAttr.GetStart() >= nFromPos && rAttr.Which() == nWhich)
    2787        8185 :             return &rAttr;
    2788             :     }
    2789      173832 :     return NULL;
    2790             : }
    2791             : 
    2792           0 : bool CharAttribList::HasAttrib( sal_uInt16 nStartPos, sal_uInt16 nEndPos ) const
    2793             : {
    2794           0 :     AttribsType::const_reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend();
    2795           0 :     for (; it != itEnd; ++it)
    2796             :     {
    2797           0 :         const EditCharAttrib& rAttr = *it;
    2798           0 :         if (rAttr.GetStart() < nEndPos && rAttr.GetEnd() > nStartPos)
    2799           0 :             return true;
    2800             :     }
    2801           0 :     return false;
    2802             : }
    2803             : 
    2804     2179494 : CharAttribList::AttribsType& CharAttribList::GetAttribs()
    2805             : {
    2806     2179494 :     return aAttribs;
    2807             : }
    2808             : 
    2809     1080770 : const CharAttribList::AttribsType& CharAttribList::GetAttribs() const
    2810             : {
    2811     1080770 :     return aAttribs;
    2812             : }
    2813             : 
    2814             : namespace {
    2815             : 
    2816             : class FindByAddress : std::unary_function<EditCharAttrib, bool>
    2817             : {
    2818             :     const EditCharAttrib* mpAttr;
    2819             : public:
    2820        1093 :     FindByAddress(const EditCharAttrib* p) : mpAttr(p) {}
    2821        2864 :     bool operator() (const EditCharAttrib& r) const
    2822             :     {
    2823        2864 :         return &r == mpAttr;
    2824             :     }
    2825             : };
    2826             : 
    2827             : }
    2828             : 
    2829           0 : void CharAttribList::Remove(const EditCharAttrib* p)
    2830             : {
    2831           0 :     AttribsType::iterator it = std::find_if(aAttribs.begin(), aAttribs.end(), FindByAddress(p));
    2832           0 :     if (it != aAttribs.end())
    2833           0 :         aAttribs.erase(it);
    2834           0 : }
    2835             : 
    2836        1200 : void CharAttribList::Remove(size_t nPos)
    2837             : {
    2838        1200 :     if (nPos >= aAttribs.size())
    2839        1200 :         return;
    2840             : 
    2841        1200 :     aAttribs.erase(aAttribs.begin()+nPos);
    2842             : }
    2843             : 
    2844        1093 : void CharAttribList::Release(const EditCharAttrib* p)
    2845             : {
    2846        1093 :     AttribsType::iterator it = std::find_if(aAttribs.begin(), aAttribs.end(), FindByAddress(p));
    2847        1093 :     if (it != aAttribs.end())
    2848        1093 :         aAttribs.release(it).release();
    2849        1093 : }
    2850             : 
    2851          25 : void CharAttribList::SetHasEmptyAttribs(bool b)
    2852             : {
    2853          25 :     bHasEmptyAttribs = b;
    2854          25 : }
    2855             : 
    2856          66 : bool CharAttribList::HasBoundingAttrib( sal_uInt16 nBound ) const
    2857             : {
    2858             :     // Backwards, if one ends where the next starts.
    2859             :     // => The starting one is the valid one ...
    2860          66 :     AttribsType::const_reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend();
    2861          66 :     for (; it != itEnd; ++it)
    2862             :     {
    2863           4 :         const EditCharAttrib& rAttr = *it;
    2864           4 :         if (rAttr.GetEnd() < nBound)
    2865           0 :             return false;
    2866             : 
    2867           4 :         if (rAttr.GetStart() == nBound || rAttr.GetEnd() == nBound)
    2868           4 :             return true;
    2869             :     }
    2870          62 :     return false;
    2871             : }
    2872             : 
    2873           0 : const EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) const
    2874             : {
    2875           0 :     if ( !bHasEmptyAttribs )
    2876           0 :         return NULL;
    2877             : 
    2878           0 :     AttribsType::const_iterator it = aAttribs.begin(), itEnd = aAttribs.end();
    2879           0 :     for (; it != itEnd; ++it)
    2880             :     {
    2881           0 :         const EditCharAttrib& rAttr = *it;
    2882           0 :         if (rAttr.GetStart() == nPos && rAttr.GetEnd() == nPos && rAttr.Which() == nWhich)
    2883           0 :             return &rAttr;
    2884             :     }
    2885           0 :     return NULL;
    2886             : }
    2887             : 
    2888        4263 : EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos )
    2889             : {
    2890        4263 :     if ( !bHasEmptyAttribs )
    2891         343 :         return NULL;
    2892             : 
    2893        3920 :     AttribsType::iterator it = aAttribs.begin(), itEnd = aAttribs.end();
    2894       28004 :     for (; it != itEnd; ++it)
    2895             :     {
    2896       25185 :         EditCharAttrib& rAttr = *it;
    2897       25185 :         if (rAttr.GetStart() == nPos && rAttr.GetEnd() == nPos && rAttr.Which() == nWhich)
    2898        1101 :             return &rAttr;
    2899             :     }
    2900        2819 :     return NULL;
    2901             : }
    2902             : 
    2903             : namespace {
    2904             : 
    2905             : class FindByStartPos : std::unary_function<EditCharAttrib, bool>
    2906             : {
    2907             :     sal_uInt16 mnPos;
    2908             : public:
    2909      212579 :     FindByStartPos(sal_uInt16 nPos) : mnPos(nPos) {}
    2910      163965 :     bool operator() (const EditCharAttrib& r) const
    2911             :     {
    2912      163965 :         return r.GetStart() >= mnPos;
    2913             :     }
    2914             : };
    2915             : 
    2916             : }
    2917             : 
    2918      212579 : const EditCharAttrib* CharAttribList::FindFeature( sal_uInt16 nPos ) const
    2919             : {
    2920             :     // First, find the first attribute that starts at or after specified position.
    2921             :     AttribsType::const_iterator it =
    2922      212579 :         std::find_if(aAttribs.begin(), aAttribs.end(), FindByStartPos(nPos));
    2923             : 
    2924      212579 :     if (it == aAttribs.end())
    2925             :         // All attributes are before the specified position.
    2926      129509 :         return NULL;
    2927             : 
    2928             :     // And find the first attribute with feature.
    2929       83070 :     it = std::find_if(it, aAttribs.end(), boost::bind(&EditCharAttrib::IsFeature, _1) == true);
    2930       83070 :     return it == aAttribs.end() ? NULL : &(*it);
    2931             : }
    2932             : 
    2933             : namespace {
    2934             : 
    2935             : class RemoveEmptyAttrItem : std::unary_function<EditCharAttrib, void>
    2936             : {
    2937             :     SfxItemPool& mrItemPool;
    2938             : public:
    2939         168 :     RemoveEmptyAttrItem(SfxItemPool& rPool) : mrItemPool(rPool) {}
    2940        1379 :     void operator() (const EditCharAttrib& r)
    2941             :     {
    2942        1379 :         if (r.IsEmpty())
    2943           0 :             mrItemPool.Remove(*r.GetItem());
    2944        1379 :     }
    2945             : };
    2946             : 
    2947             : }
    2948             : 
    2949         168 : void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool )
    2950             : {
    2951         168 :     std::for_each(aAttribs.begin(), aAttribs.end(), RemoveEmptyAttrItem(rItemPool));
    2952         168 :     aAttribs.erase_if(boost::bind(&EditCharAttrib::IsEmpty, _1) == true);
    2953         168 :     bHasEmptyAttribs = false;
    2954         168 : }
    2955             : 
    2956             : #if OSL_DEBUG_LEVEL > 2
    2957             : bool CharAttribList::DbgCheckAttribs() const
    2958             : {
    2959             :     bool bOK = true;
    2960             :     AttribsType::const_iterator it = aAttribs.begin(), itEnd = aAttribs.end();
    2961             :     for (; it != itEnd; ++it)
    2962             :     {
    2963             :         const EditCharAttrib& rAttr = *it;
    2964             :         if (rAttr.GetStart() > rAttr.GetEnd())
    2965             :         {
    2966             :             bOK = false;
    2967             :             OSL_FAIL( "Attribute is distorted" );
    2968             :         }
    2969             :         else if (rAttr.IsFeature() && rAttr.GetLen() != 1)
    2970             :         {
    2971             :             bOK = false;
    2972             :             OSL_FAIL( "Feature, Len != 1" );
    2973             :         }
    2974             :     }
    2975             :     return bOK;
    2976             : }
    2977             : #endif
    2978             : 
    2979             : 
    2980           0 : SvxColorList::SvxColorList()
    2981             : {
    2982           0 : }
    2983             : 
    2984           0 : SvxColorList::~SvxColorList()
    2985             : {
    2986           0 :     for ( size_t i = 0, n = aColorList.size(); i < n; ++i )
    2987           0 :         delete aColorList[ i ];
    2988           0 :     aColorList.clear();
    2989           0 : }
    2990             : 
    2991           0 : size_t SvxColorList::GetId( const SvxColorItem& rColorItem )
    2992             : {
    2993           0 :     for ( size_t i = 0, n = aColorList.size(); i < n; ++i )
    2994           0 :         if ( *aColorList[ i ] == rColorItem )
    2995           0 :             return i;
    2996             :     DBG_WARNING( "Color not found: GetId()" );
    2997           0 :     return 0;
    2998             : }
    2999             : 
    3000           0 : void SvxColorList::Insert( SvxColorItem* pItem, size_t nIndex )
    3001             : {
    3002           0 :     if ( nIndex >= aColorList.size() )
    3003             :     {
    3004           0 :         aColorList.push_back( pItem );
    3005             :     }
    3006             :     else
    3007             :     {
    3008           0 :         DummyColorList::iterator it = aColorList.begin();
    3009           0 :         ::std::advance( it, nIndex );
    3010           0 :         aColorList.insert( it, pItem );
    3011             :     }
    3012           0 : }
    3013             : 
    3014           0 : SvxColorItem* SvxColorList::GetObject( size_t nIndex )
    3015             : {
    3016           0 :     return ( nIndex >= aColorList.size() ) ? NULL : aColorList[ nIndex ];
    3017             : }
    3018             : 
    3019       24585 : EditEngineItemPool::EditEngineItemPool( sal_Bool bPersistenRefCounts )
    3020             :     : SfxItemPool( String( "EditEngineItemPool", RTL_TEXTENCODING_ASCII_US ), EE_ITEMS_START, EE_ITEMS_END,
    3021       24585 :                     aItemInfos, 0, bPersistenRefCounts )
    3022             : {
    3023       24585 :     SetVersionMap( 1, 3999, 4015, aV1Map );
    3024       24585 :     SetVersionMap( 2, 3999, 4019, aV2Map );
    3025       24585 :     SetVersionMap( 3, 3997, 4020, aV3Map );
    3026       24585 :     SetVersionMap( 4, 3994, 4022, aV4Map );
    3027       24585 :     SetVersionMap( 5, 3994, 4037, aV5Map );
    3028             : 
    3029       24585 :     SfxPoolItem** ppDefItems = EE_DLL().GetGlobalData()->GetDefItems();
    3030       24585 :     SetDefaults( ppDefItems );
    3031       24585 : }
    3032             : 
    3033       48564 : EditEngineItemPool::~EditEngineItemPool()
    3034             : {
    3035       48564 : }
    3036             : 
    3037        2456 : SvStream& EditEngineItemPool::Store( SvStream& rStream ) const
    3038             : {
    3039             :     // for a 3.1 export a hack has to be installed, as in there is a BUG in
    3040             :     // SfxItemSet::Load, but not subsequently after 3.1.
    3041             : 
    3042             :     // The selected range must be kept after Store, because itemsets are not
    3043             :     // stored until then...
    3044             : 
    3045        2456 :     long nVersion = rStream.GetVersion();
    3046           0 :     sal_Bool b31Format = ( nVersion && ( nVersion <= SOFFICE_FILEFORMAT_31 ) )
    3047        2456 :                         ? sal_True : sal_False;
    3048             : 
    3049        2456 :     EditEngineItemPool* pThis = (EditEngineItemPool*)this;
    3050        2456 :     if ( b31Format )
    3051           0 :         pThis->SetStoringRange( 3997, 4022 );
    3052             :     else
    3053        2456 :         pThis->SetStoringRange( EE_ITEMS_START, EE_ITEMS_END );
    3054             : 
    3055        2456 :     return SfxItemPool::Store( rStream );
    3056         267 : }
    3057             : 
    3058             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10