LCOV - code coverage report
Current view: top level - libreoffice/editeng/source/editeng - editdoc.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1016 1408 72.2 %
Date: 2012-12-27 Functions: 161 201 80.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10