LCOV - code coverage report
Current view: top level - editeng/source/editeng - editdoc.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 1097 1389 79.0 %
Date: 2014-04-11 Functions: 169 205 82.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10