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

Generated by: LCOV version 1.10