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

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

Generated by: LCOV version 1.10