| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_editeng.hxx" |
| |
| #include <vcl/wrkwin.hxx> |
| #include <vcl/dialog.hxx> |
| #include <vcl/msgbox.hxx> |
| #include <vcl/svapp.hxx> |
| |
| #include <editeng/tstpitem.hxx> |
| #include <editeng/colritem.hxx> |
| #include <editeng/fontitem.hxx> |
| #include <editeng/crsditem.hxx> |
| #include <editeng/fhgtitem.hxx> |
| #include <editeng/postitem.hxx> |
| #include <editeng/kernitem.hxx> |
| #include <editeng/wrlmitem.hxx> |
| #include <editeng/wghtitem.hxx> |
| #include <editeng/udlnitem.hxx> |
| #include <editeng/cntritem.hxx> |
| #include <editeng/escpitem.hxx> |
| #include <editeng/shdditem.hxx> |
| #include <editeng/akrnitem.hxx> |
| #include <editeng/cscoitem.hxx> |
| #include <editeng/langitem.hxx> |
| #include <editeng/emphitem.hxx> |
| #include <editeng/charscaleitem.hxx> |
| #include <editeng/charreliefitem.hxx> |
| #include <editeng/xmlcnitm.hxx> |
| #include <editeng/editids.hrc> |
| |
| #include <editdoc.hxx> |
| #include <editdbg.hxx> |
| #include <editeng/eerdll.hxx> |
| #include <eerdll2.hxx> |
| #include <tools/stream.hxx> |
| #include <tools/debug.hxx> |
| #include <tools/shl.hxx> |
| #include <vcl/svapp.hxx> |
| #include <com/sun/star/i18n/ScriptType.hpp> |
| #include <stdlib.h> // qsort |
| |
| using namespace ::com::sun::star; |
| |
| |
| // ------------------------------------------------------------ |
| |
| sal_uInt16 GetScriptItemId( sal_uInt16 nItemId, short nScriptType ) |
| { |
| sal_uInt16 nId = nItemId; |
| |
| if ( ( nScriptType == i18n::ScriptType::ASIAN ) || |
| ( nScriptType == i18n::ScriptType::COMPLEX ) ) |
| { |
| switch ( nItemId ) |
| { |
| case EE_CHAR_LANGUAGE: |
| nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_LANGUAGE_CJK : EE_CHAR_LANGUAGE_CTL; |
| break; |
| case EE_CHAR_FONTINFO: |
| nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK : EE_CHAR_FONTINFO_CTL; |
| break; |
| case EE_CHAR_FONTHEIGHT: |
| nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTHEIGHT_CJK : EE_CHAR_FONTHEIGHT_CTL; |
| break; |
| case EE_CHAR_WEIGHT: |
| nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_WEIGHT_CJK : EE_CHAR_WEIGHT_CTL; |
| break; |
| case EE_CHAR_ITALIC: |
| nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL; |
| break; |
| } |
| } |
| |
| return nId; |
| } |
| |
| sal_Bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType ) |
| { |
| sal_Bool bValid = sal_True; |
| |
| switch ( nItemId ) |
| { |
| case EE_CHAR_LANGUAGE: |
| bValid = nScriptType == i18n::ScriptType::LATIN; |
| break; |
| case EE_CHAR_LANGUAGE_CJK: |
| bValid = nScriptType == i18n::ScriptType::ASIAN; |
| break; |
| case EE_CHAR_LANGUAGE_CTL: |
| bValid = nScriptType == i18n::ScriptType::COMPLEX; |
| break; |
| case EE_CHAR_FONTINFO: |
| bValid = nScriptType == i18n::ScriptType::LATIN; |
| break; |
| case EE_CHAR_FONTINFO_CJK: |
| bValid = nScriptType == i18n::ScriptType::ASIAN; |
| break; |
| case EE_CHAR_FONTINFO_CTL: |
| bValid = nScriptType == i18n::ScriptType::COMPLEX; |
| break; |
| case EE_CHAR_FONTHEIGHT: |
| bValid = nScriptType == i18n::ScriptType::LATIN; |
| break; |
| case EE_CHAR_FONTHEIGHT_CJK: |
| bValid = nScriptType == i18n::ScriptType::ASIAN; |
| break; |
| case EE_CHAR_FONTHEIGHT_CTL: |
| bValid = nScriptType == i18n::ScriptType::COMPLEX; |
| break; |
| case EE_CHAR_WEIGHT: |
| bValid = nScriptType == i18n::ScriptType::LATIN; |
| break; |
| case EE_CHAR_WEIGHT_CJK: |
| bValid = nScriptType == i18n::ScriptType::ASIAN; |
| break; |
| case EE_CHAR_WEIGHT_CTL: |
| bValid = nScriptType == i18n::ScriptType::COMPLEX; |
| break; |
| case EE_CHAR_ITALIC: |
| bValid = nScriptType == i18n::ScriptType::LATIN; |
| break; |
| case EE_CHAR_ITALIC_CJK: |
| bValid = nScriptType == i18n::ScriptType::ASIAN; |
| break; |
| case EE_CHAR_ITALIC_CTL: |
| bValid = nScriptType == i18n::ScriptType::COMPLEX; |
| break; |
| } |
| |
| return bValid; |
| } |
| |
| |
| // ------------------------------------------------------------ |
| |
| // Sollte spaeter zentral nach TOOLS/STRING (Aktuell: 303) |
| // fuer Grep: WS_TARGET |
| |
| DBG_NAME( EE_TextPortion ); |
| DBG_NAME( EE_EditLine ); |
| DBG_NAME( EE_ContentNode ); |
| DBG_NAME( EE_CharAttribList ); |
| |
| SfxItemInfo aItemInfos[EDITITEMCOUNT] = { |
| { SID_ATTR_FRAMEDIRECTION, SFX_ITEM_POOLABLE }, // EE_PARA_WRITINGDIR |
| { 0, SFX_ITEM_POOLABLE }, // EE_PARA_XMLATTRIBS |
| { SID_ATTR_PARA_HANGPUNCTUATION, SFX_ITEM_POOLABLE }, // EE_PARA_HANGINGPUNCTUATION |
| { SID_ATTR_PARA_FORBIDDEN_RULES, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_PARA_SCRIPTSPACE, SFX_ITEM_POOLABLE }, // EE_PARA_ASIANCJKSPACING |
| { SID_ATTR_NUMBERING_RULE, SFX_ITEM_POOLABLE }, // EE_PARA_NUMBULL |
| { 0, SFX_ITEM_POOLABLE }, // EE_PARA_HYPHENATE |
| { 0, SFX_ITEM_POOLABLE }, // EE_PARA_BULLETSTATE |
| { 0, SFX_ITEM_POOLABLE }, // EE_PARA_OUTLLRSPACE |
| { SID_ATTR_PARA_OUTLLEVEL, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_PARA_BULLET, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_LRSPACE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_ULSPACE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_PARA_LINESPACE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_PARA_ADJUST, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_TABSTOP, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_COLOR, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_FONT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_SCALEWIDTH, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_WEIGHT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_UNDERLINE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_STRIKEOUT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_POSTURE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CONTOUR, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_SHADOWED, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_ESCAPEMENT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_AUTOKERN, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_KERNING, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_WORDLINEMODE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_LANGUAGE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CJK_LANGUAGE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CTL_LANGUAGE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CJK_FONT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CTL_FONT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CJK_FONTHEIGHT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CTL_FONTHEIGHT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CJK_WEIGHT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CTL_WEIGHT, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CJK_POSTURE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_CTL_POSTURE, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_EMPHASISMARK, SFX_ITEM_POOLABLE }, |
| { SID_ATTR_CHAR_RELIEF, SFX_ITEM_POOLABLE }, |
| { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_RUBI_DUMMY |
| { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_XMLATTRIBS |
| { SID_ATTR_CHAR_OVERLINE, SFX_ITEM_POOLABLE }, |
| { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_TAB |
| { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_LINEBR |
| { SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEM_POOLABLE }, // EE_FEATURE_NOTCONV |
| { SID_FIELD, SFX_ITEM_POOLABLE } |
| }; |
| |
| sal_uInt16 aV1Map[] = { |
| 3999, 4001, 4002, 4003, 4004, 4005, 4006, |
| 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4017, 4018, 4019 // MI: 4019? |
| }; |
| |
| sal_uInt16 aV2Map[] = { |
| 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, |
| 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4018, 4019, 4020 |
| }; |
| |
| sal_uInt16 aV3Map[] = { |
| 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, |
| 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, |
| 4020, 4021 |
| }; |
| |
| sal_uInt16 aV4Map[] = { |
| 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, |
| 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, |
| 4014, 4015, 4016, 4017, 4018, |
| /* CJK Items inserted here: EE_CHAR_LANGUAGE - EE_CHAR_XMLATTRIBS */ |
| 4034, 4035, 4036, 4037 |
| }; |
| |
| sal_uInt16 aV5Map[] = { |
| 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, |
| 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, |
| 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, |
| 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, |
| /* EE_CHAR_OVERLINE inserted here */ |
| 4035, 4036, 4037, 4038 |
| }; |
| |
| SV_IMPL_PTRARR( DummyContentList, ContentNode* ); |
| |
| int SAL_CALL CompareStart( const void* pFirst, const void* pSecond ) |
| { |
| if ( (*((EditCharAttrib**)pFirst))->GetStart() < (*((EditCharAttrib**)pSecond))->GetStart() ) |
| return (-1); |
| else if ( (*((EditCharAttrib**)pFirst))->GetStart() > (*((EditCharAttrib**)pSecond))->GetStart() ) |
| return (1); |
| return 0; |
| } |
| |
| EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_uInt16 nS, sal_uInt16 nE ) |
| { |
| // das neue Attribut im Pool anlegen |
| const SfxPoolItem& rNew = rPool.Put( rAttr ); |
| |
| EditCharAttrib* pNew = 0; |
| switch( rNew.Which() ) |
| { |
| case EE_CHAR_LANGUAGE: |
| case EE_CHAR_LANGUAGE_CJK: |
| case EE_CHAR_LANGUAGE_CTL: |
| { |
| pNew = new EditCharAttribLanguage( (const SvxLanguageItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_COLOR: |
| { |
| pNew = new EditCharAttribColor( (const SvxColorItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_FONTINFO: |
| case EE_CHAR_FONTINFO_CJK: |
| case EE_CHAR_FONTINFO_CTL: |
| { |
| pNew = new EditCharAttribFont( (const SvxFontItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_FONTHEIGHT: |
| case EE_CHAR_FONTHEIGHT_CJK: |
| case EE_CHAR_FONTHEIGHT_CTL: |
| { |
| pNew = new EditCharAttribFontHeight( (const SvxFontHeightItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_FONTWIDTH: |
| { |
| pNew = new EditCharAttribFontWidth( (const SvxCharScaleWidthItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_WEIGHT: |
| case EE_CHAR_WEIGHT_CJK: |
| case EE_CHAR_WEIGHT_CTL: |
| { |
| pNew = new EditCharAttribWeight( (const SvxWeightItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_UNDERLINE: |
| { |
| pNew = new EditCharAttribUnderline( (const SvxUnderlineItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_OVERLINE: |
| { |
| pNew = new EditCharAttribOverline( (const SvxOverlineItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_EMPHASISMARK: |
| { |
| pNew = new EditCharAttribEmphasisMark( (const SvxEmphasisMarkItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_RELIEF: |
| { |
| pNew = new EditCharAttribRelief( (const SvxCharReliefItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_STRIKEOUT: |
| { |
| pNew = new EditCharAttribStrikeout( (const SvxCrossedOutItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_ITALIC: |
| case EE_CHAR_ITALIC_CJK: |
| case EE_CHAR_ITALIC_CTL: |
| { |
| pNew = new EditCharAttribItalic( (const SvxPostureItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_OUTLINE: |
| { |
| pNew = new EditCharAttribOutline( (const SvxContourItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_SHADOW: |
| { |
| pNew = new EditCharAttribShadow( (const SvxShadowedItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_ESCAPEMENT: |
| { |
| pNew = new EditCharAttribEscapement( (const SvxEscapementItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_PAIRKERNING: |
| { |
| pNew = new EditCharAttribPairKerning( (const SvxAutoKernItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_KERNING: |
| { |
| pNew = new EditCharAttribKerning( (const SvxKerningItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_WLM: |
| { |
| pNew = new EditCharAttribWordLineMode( (const SvxWordLineModeItem&)rNew, nS, nE ); |
| } |
| break; |
| case EE_CHAR_XMLATTRIBS: |
| { |
| pNew = new EditCharAttrib( rNew, nS, nE ); // Attrib is only for holding XML information... |
| } |
| break; |
| case EE_FEATURE_TAB: |
| { |
| pNew = new EditCharAttribTab( (const SfxVoidItem&)rNew, nS ); |
| } |
| break; |
| case EE_FEATURE_LINEBR: |
| { |
| pNew = new EditCharAttribLineBreak( (const SfxVoidItem&)rNew, nS ); |
| } |
| break; |
| case EE_FEATURE_FIELD: |
| { |
| pNew = new EditCharAttribField( (const SvxFieldItem&)rNew, nS ); |
| } |
| break; |
| default: |
| { |
| DBG_ERROR( "Ungueltiges Attribut!" ); |
| } |
| } |
| return pNew; |
| } |
| |
| // ------------------------------------------------------------------------- |
| // class EditLine |
| // ------------------------------------------------------------------------- |
| |
| EditLine::EditLine() |
| { |
| DBG_CTOR( EE_EditLine, 0 ); |
| |
| nStart = nEnd = 0; |
| nStartPortion = 0; // damit in ungueltiger Zeile ohne Portions von einer gueltigen Zeile mit der Portion Nr0 unterscieden werden kann. |
| nEndPortion = 0; |
| nHeight = 0; |
| nStartPosX = 0; |
| nTxtHeight = 0; |
| nTxtWidth = 0; |
| nCrsrHeight = 0; |
| nMaxAscent = 0; |
| bHangingPunctuation = sal_False; |
| bInvalid = sal_True; |
| } |
| |
| EditLine::EditLine( const EditLine& r ) |
| { |
| DBG_CTOR( EE_EditLine, 0 ); |
| |
| nEnd = r.nEnd; |
| nStart = r.nStart; |
| nStartPortion = r.nStartPortion; |
| nEndPortion = r.nEndPortion; |
| bHangingPunctuation = r.bHangingPunctuation; |
| |
| nHeight = 0; |
| nStartPosX = 0; |
| nTxtHeight = 0; |
| nTxtWidth = 0; |
| nCrsrHeight = 0; |
| nMaxAscent = 0; |
| bInvalid = sal_True; |
| } |
| |
| EditLine::~EditLine() |
| { |
| DBG_DTOR( EE_EditLine, 0 ); |
| } |
| |
| EditLine* EditLine::Clone() const |
| { |
| EditLine* pL = new EditLine; |
| if ( aPositions.Count() ) |
| { |
| pL->aPositions.Insert (aPositions.GetData(), aPositions.Count(), 0); |
| } |
| pL->nStartPosX = nStartPosX; |
| pL->nStart = nStart; |
| pL->nEnd = nEnd; |
| pL->nStartPortion = nStartPortion; |
| pL->nEndPortion = nEndPortion; |
| pL->nHeight = nHeight; |
| pL->nTxtWidth = nTxtWidth; |
| pL->nTxtHeight = nTxtHeight; |
| pL->nCrsrHeight = nCrsrHeight; |
| pL->nMaxAscent = nMaxAscent; |
| |
| return pL; |
| } |
| |
| sal_Bool operator == ( const EditLine& r1, const EditLine& r2 ) |
| { |
| if ( r1.nStart != r2.nStart ) |
| return sal_False; |
| |
| if ( r1.nEnd != r2.nEnd ) |
| return sal_False; |
| |
| if ( r1.nStartPortion != r2.nStartPortion ) |
| return sal_False; |
| |
| if ( r1.nEndPortion != r2.nEndPortion ) |
| return sal_False; |
| |
| return sal_True; |
| } |
| |
| EditLine& EditLine::operator = ( const EditLine& r ) |
| { |
| nEnd = r.nEnd; |
| nStart = r.nStart; |
| nEndPortion = r.nEndPortion; |
| nStartPortion = r.nStartPortion; |
| return *this; |
| } |
| |
| |
| sal_Bool operator != ( const EditLine& r1, const EditLine& r2 ) |
| { |
| return !( r1 == r2 ); |
| } |
| |
| Size EditLine::CalcTextSize( ParaPortion& rParaPortion ) |
| { |
| Size aSz; |
| Size aTmpSz; |
| TextPortion* pPortion; |
| |
| sal_uInt16 nIndex = GetStart(); |
| |
| DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize vor CreatePortions !" ); |
| |
| for ( sal_uInt16 n = nStartPortion; n <= nEndPortion; n++ ) |
| { |
| pPortion = rParaPortion.GetTextPortions().GetObject(n); |
| switch ( pPortion->GetKind() ) |
| { |
| case PORTIONKIND_TEXT: |
| case PORTIONKIND_FIELD: |
| case PORTIONKIND_HYPHENATOR: |
| { |
| aTmpSz = pPortion->GetSize(); |
| aSz.Width() += aTmpSz.Width(); |
| if ( aSz.Height() < aTmpSz.Height() ) |
| aSz.Height() = aTmpSz.Height(); |
| } |
| break; |
| case PORTIONKIND_TAB: |
| // case PORTIONKIND_EXTRASPACE: |
| { |
| aSz.Width() += pPortion->GetSize().Width(); |
| } |
| break; |
| } |
| nIndex = nIndex + pPortion->GetLen(); |
| } |
| |
| SetHeight( (sal_uInt16)aSz.Height() ); |
| return aSz; |
| } |
| |
| // ------------------------------------------------------------------------- |
| // class EditLineList |
| // ------------------------------------------------------------------------- |
| EditLineList::EditLineList() |
| { |
| } |
| |
| EditLineList::~EditLineList() |
| { |
| Reset(); |
| } |
| |
| void EditLineList::Reset() |
| { |
| for ( sal_uInt16 nLine = 0; nLine < Count(); nLine++ ) |
| delete GetObject(nLine); |
| Remove( 0, Count() ); |
| } |
| |
| void EditLineList::DeleteFromLine( sal_uInt16 nDelFrom ) |
| { |
| DBG_ASSERT( nDelFrom <= (Count() - 1), "DeleteFromLine: Out of range" ); |
| for ( sal_uInt16 nL = nDelFrom; nL < Count(); nL++ ) |
| delete GetObject(nL); |
| Remove( nDelFrom, Count()-nDelFrom ); |
| } |
| |
| sal_uInt16 EditLineList::FindLine( sal_uInt16 nChar, sal_Bool bInclEnd ) |
| { |
| for ( sal_uInt16 nLine = 0; nLine < Count(); nLine++ ) |
| { |
| EditLine* pLine = GetObject( nLine ); |
| if ( ( bInclEnd && ( pLine->GetEnd() >= nChar ) ) || |
| ( pLine->GetEnd() > nChar ) ) |
| { |
| return nLine; |
| } |
| } |
| |
| DBG_ASSERT( !bInclEnd, "Zeile nicht gefunden: FindLine" ); |
| return ( Count() - 1 ); |
| } |
| |
| // ------------------------------------------------------------------------- |
| // class EditSelection |
| // ------------------------------------------------------------------------- |
| sal_Bool EditPaM::DbgIsBuggy( EditDoc& rDoc ) |
| { |
| if ( !pNode ) |
| return sal_True; |
| if ( rDoc.GetPos( pNode ) >= rDoc.Count() ) |
| return sal_True; |
| if ( nIndex > pNode->Len() ) |
| return sal_True; |
| |
| return sal_False; |
| } |
| |
| sal_Bool EditSelection::DbgIsBuggy( EditDoc& rDoc ) |
| { |
| if ( aStartPaM.DbgIsBuggy( rDoc ) ) |
| return sal_True; |
| if ( aEndPaM.DbgIsBuggy( rDoc ) ) |
| return sal_True; |
| |
| return sal_False; |
| } |
| |
| EditSelection::EditSelection() |
| { |
| } |
| |
| EditSelection::EditSelection( const EditPaM& rStartAndAnd ) |
| { |
| // koennte noch optimiert werden! |
| // nicht erst Def-CTOR vom PaM rufen! |
| aStartPaM = rStartAndAnd; |
| aEndPaM = rStartAndAnd; |
| } |
| |
| EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd ) |
| { |
| // koennte noch optimiert werden! |
| aStartPaM = rStart; |
| aEndPaM = rEnd; |
| } |
| |
| EditSelection& EditSelection::operator = ( const EditPaM& rPaM ) |
| { |
| aStartPaM = rPaM; |
| aEndPaM = rPaM; |
| return *this; |
| } |
| |
| sal_Bool EditSelection::IsInvalid() const |
| { |
| EditPaM aEmptyPaM; |
| |
| if ( aStartPaM == aEmptyPaM ) |
| return sal_True; |
| |
| if ( aEndPaM == aEmptyPaM ) |
| return sal_True; |
| |
| return sal_False; |
| } |
| |
| sal_Bool EditSelection::Adjust( const ContentList& rNodes ) |
| { |
| DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index im Wald in Adjust(1)" ); |
| DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index im Wald in Adjust(2)" ); |
| |
| ContentNode* pStartNode = aStartPaM.GetNode(); |
| ContentNode* pEndNode = aEndPaM.GetNode(); |
| |
| sal_uInt16 nStartNode = rNodes.GetPos( pStartNode ); |
| sal_uInt16 nEndNode = rNodes.GetPos( pEndNode ); |
| |
| DBG_ASSERT( nStartNode != USHRT_MAX, "Node im Wald in Adjust(1)" ); |
| DBG_ASSERT( nEndNode != USHRT_MAX, "Node im Wald in Adjust(2)" ); |
| |
| sal_Bool bSwap = sal_False; |
| if ( nStartNode > nEndNode ) |
| bSwap = sal_True; |
| else if ( ( nStartNode == nEndNode ) && ( aStartPaM.GetIndex() > aEndPaM.GetIndex() ) ) |
| bSwap = sal_True; |
| |
| if ( bSwap ) |
| { |
| EditPaM aTmpPaM( aStartPaM ); |
| aStartPaM = aEndPaM; |
| aEndPaM = aTmpPaM; |
| } |
| |
| return bSwap; |
| } |
| |
| |
| // ------------------------------------------------------------------------- |
| // class EditPaM |
| // ------------------------------------------------------------------------- |
| sal_Bool operator == ( const EditPaM& r1, const EditPaM& r2 ) |
| { |
| if ( r1.GetNode() != r2.GetNode() ) |
| return sal_False; |
| |
| if ( r1.GetIndex() != r2.GetIndex() ) |
| return sal_False; |
| |
| return sal_True; |
| } |
| |
| EditPaM& EditPaM::operator = ( const EditPaM& rPaM ) |
| { |
| nIndex = rPaM.nIndex; |
| pNode = rPaM.pNode; |
| return *this; |
| } |
| |
| sal_Bool operator != ( const EditPaM& r1, const EditPaM& r2 ) |
| { |
| return !( r1 == r2 ); |
| } |
| |
| |
| // ------------------------------------------------------------------------- |
| // class ContentNode |
| // ------------------------------------------------------------------------- |
| ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool ) |
| { |
| DBG_CTOR( EE_ContentNode, 0 ); |
| pWrongList = NULL; |
| } |
| |
| ContentNode::ContentNode( const XubString& rStr, const ContentAttribs& rContentAttribs ) : |
| XubString( rStr ), aContentAttribs( rContentAttribs ) |
| { |
| DBG_CTOR( EE_ContentNode, 0 ); |
| pWrongList = NULL; |
| } |
| |
| ContentNode::~ContentNode() |
| { |
| DBG_DTOR( EE_ContentNode, 0 ); |
| #ifndef SVX_LIGHT |
| delete pWrongList; |
| #endif |
| } |
| |
| void ContentNode::ExpandAttribs( sal_uInt16 nIndex, sal_uInt16 nNew, SfxItemPool& rItemPool ) |
| { |
| if ( !nNew ) |
| return; |
| |
| // Da Features anders behandelt werden als normale Zeichenattribute, |
| // kann sich hier auch die Sortierung der Start-Liste aendern! |
| // In jedem if..., in dem weiter (n) Moeglichkeiten aufgrund von |
| // bFeature oder Spezialfall existieren, |
| // muessen (n-1) Moeglichkeiten mit bResort versehen werden. |
| // Die wahrscheinlichste Moeglichkeit erhaelt kein bResort, |
| // so dass nicht neu sortiert wird, wenn sich alle Attribute |
| // gleich verhalten. |
| sal_Bool bResort = sal_False; |
| sal_Bool bExpandedEmptyAtIndexNull = sal_False; |
| |
| sal_uInt16 nAttr = 0; |
| EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); |
| while ( pAttrib ) |
| { |
| if ( pAttrib->GetEnd() >= nIndex ) |
| { |
| // Alle Attribute hinter der Einfuegeposition verschieben... |
| if ( pAttrib->GetStart() > nIndex ) |
| { |
| pAttrib->MoveForward( nNew ); |
| } |
| // 0: Leeres Attribut expandieren, wenn an Einfuegestelle |
| else if ( pAttrib->IsEmpty() ) |
| { |
| // Index nicht pruefen, leeres durfte nur dort liegen. |
| // Wenn spaeter doch Ueberpruefung: |
| // Spezialfall: Start == 0; AbsLen == 1, nNew = 1 => Expand, weil durch Absatzumbruch! |
| // Start <= nIndex, End >= nIndex => Start=End=nIndex! |
| // if ( pAttrib->GetStart() == nIndex ) |
| pAttrib->Expand( nNew ); |
| if ( pAttrib->GetStart() == 0 ) |
| bExpandedEmptyAtIndexNull = sal_True; |
| } |
| // 1: Attribut startet davor, geht bis Index... |
| else if ( pAttrib->GetEnd() == nIndex ) // Start muss davor liegen |
| { |
| // Nur expandieren, wenn kein Feature, |
| // und wenn nicht in ExcludeListe! |
| // Sonst geht z.B. ein UL bis zum neuen ULDB, beide expandieren |
| // if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) ) |
| if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) |
| { |
| if ( !pAttrib->IsEdge() ) |
| pAttrib->Expand( nNew ); |
| } |
| else |
| bResort = sal_True; |
| } |
| // 2: Attribut startet davor, geht hinter Index... |
| else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) |
| { |
| DBG_ASSERT( !pAttrib->IsFeature(), "Grosses Feature?!" ); |
| pAttrib->Expand( nNew ); |
| } |
| // 3: Attribut startet auf Index... |
| else if ( pAttrib->GetStart() == nIndex ) |
| { |
| if ( pAttrib->IsFeature() ) |
| { |
| pAttrib->MoveForward( nNew ); |
| bResort = sal_True; |
| } |
| else |
| { |
| sal_Bool bExpand = sal_False; |
| if ( nIndex == 0 ) |
| { |
| bExpand = sal_True; |
| if( bExpandedEmptyAtIndexNull ) |
| { |
| // Check if this kind of attribut was empty and expanded here... |
| sal_uInt16 nW = pAttrib->GetItem()->Which(); |
| for ( sal_uInt16 nA = 0; nA < nAttr; nA++ ) |
| { |
| EditCharAttrib* pA = aCharAttribList.GetAttribs()[nA]; |
| if ( ( pA->GetStart() == 0 ) && ( pA->GetItem()->Which() == nW ) ) |
| { |
| bExpand = sal_False; |
| break; |
| } |
| } |
| |
| } |
| } |
| if ( bExpand ) |
| { |
| pAttrib->Expand( nNew ); |
| bResort = sal_True; |
| } |
| else |
| { |
| pAttrib->MoveForward( nNew ); |
| } |
| } |
| } |
| } |
| |
| if ( pAttrib->IsEdge() ) |
| pAttrib->SetEdge( sal_False ); |
| |
| DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); |
| |
| DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribut verdreht!" ); |
| DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attrib groesser als Absatz!" ); |
| if ( pAttrib->IsEmpty() ) |
| { |
| DBG_ERROR( "Leeres Attribut nach ExpandAttribs?" ); |
| bResort = sal_True; |
| aCharAttribList.GetAttribs().Remove( nAttr ); |
| rItemPool.Remove( *pAttrib->GetItem() ); |
| delete pAttrib; |
| nAttr--; |
| } |
| nAttr++; |
| pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); |
| } |
| |
| if ( bResort ) |
| aCharAttribList.ResortAttribs(); |
| |
| #ifndef SVX_LIGHT |
| if ( pWrongList ) |
| { |
| sal_Bool bSep = ( GetChar( nIndex ) == ' ' ) || IsFeature( nIndex ); |
| pWrongList->TextInserted( nIndex, nNew, bSep ); |
| } |
| #endif // !SVX_LIGHT |
| |
| #ifdef EDITDEBUG |
| DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), sal_True ), "Expand: Start-Liste verdreht" ); |
| #endif |
| } |
| |
| void ContentNode::CollapsAttribs( sal_uInt16 nIndex, sal_uInt16 nDeleted, SfxItemPool& rItemPool ) |
| { |
| if ( !nDeleted ) |
| return; |
| |
| // Da Features anders behandelt werden als normale Zeichenattribute, |
| // kann sich hier auch die Sortierung der Start-Liste aendern! |
| sal_Bool bResort = sal_False; |
| sal_Bool bDelAttr = sal_False; |
| sal_uInt16 nEndChanges = nIndex+nDeleted; |
| |
| sal_uInt16 nAttr = 0; |
| EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); |
| while ( pAttrib ) |
| { |
| bDelAttr = sal_False; |
| if ( pAttrib->GetEnd() >= nIndex ) |
| { |
| // Alles Attribute hinter der Einfuegeposition verschieben... |
| if ( pAttrib->GetStart() >= nEndChanges ) |
| { |
| pAttrib->MoveBackward( nDeleted ); |
| } |
| // 1. Innenliegende Attribute loeschen... |
| else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) ) |
| { |
| // Spezialfall: Attrubt deckt genau den Bereich ab |
| // => als leeres Attribut behalten. |
| if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) |
| pAttrib->GetEnd() = nIndex; // leer |
| else |
| bDelAttr = sal_True; |
| } |
| // 2. Attribut beginnt davor, endet drinnen oder dahinter... |
| else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) |
| { |
| DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" ); |
| if ( pAttrib->GetEnd() <= nEndChanges ) // endet drinnen |
| pAttrib->GetEnd() = nIndex; |
| else |
| pAttrib->Collaps( nDeleted ); // endet dahinter |
| } |
| // 3. Attribut beginnt drinnen, endet dahinter... |
| else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) ) |
| { |
| // Features duerfen nicht expandieren! |
| if ( pAttrib->IsFeature() ) |
| { |
| pAttrib->MoveBackward( nDeleted ); |
| bResort = sal_True; |
| } |
| else |
| { |
| pAttrib->GetStart() = nEndChanges; |
| pAttrib->MoveBackward( nDeleted ); |
| } |
| } |
| } |
| DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); |
| |
| DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut verdreht!" ); |
| DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collaps: Attrib groesser als Absatz!" ); |
| if ( bDelAttr /* || pAttrib->IsEmpty() */ ) |
| { |
| bResort = sal_True; |
| aCharAttribList.GetAttribs().Remove( nAttr ); |
| rItemPool.Remove( *pAttrib->GetItem() ); |
| delete pAttrib; |
| nAttr--; |
| } |
| else if ( pAttrib->IsEmpty() ) |
| aCharAttribList.HasEmptyAttribs() = sal_True; |
| |
| nAttr++; |
| pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); |
| } |
| |
| if ( bResort ) |
| aCharAttribList.ResortAttribs(); |
| |
| #ifndef SVX_LIGHT |
| if ( pWrongList ) |
| pWrongList->TextDeleted( nIndex, nDeleted ); |
| #endif // !SVX_LIGHT |
| |
| #ifdef EDITDEBUG |
| DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), sal_True ), "Collaps: Start-Liste verdreht" ); |
| #endif |
| } |
| |
| void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, sal_Bool bKeepEndingAttribs ) |
| { |
| DBG_ASSERT( pPrevNode, "kopieren von Attributen auf einen NULL-Pointer ?" ); |
| |
| xub_StrLen nCut = pPrevNode->Len(); |
| |
| sal_uInt16 nAttr = 0; |
| EditCharAttrib* pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr ); |
| while ( pAttrib ) |
| { |
| if ( pAttrib->GetEnd() < nCut ) |
| { |
| // bleiben unveraendert.... |
| ; |
| } |
| else if ( pAttrib->GetEnd() == nCut ) |
| { |
| // muessen als leeres Attribut kopiert werden. |
| if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) ) |
| { |
| EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 ); |
| DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" ); |
| aCharAttribList.InsertAttrib( pNewAttrib ); |
| } |
| } |
| else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) ) |
| { |
| // Wenn ganz vorne gecuttet wird, muss das Attribut erhalten bleiben! |
| // muessen kopiert und geaendert werden |
| EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut ); |
| DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" ); |
| aCharAttribList.InsertAttrib( pNewAttrib ); |
| // stutzen: |
| pAttrib->GetEnd() = nCut; |
| } |
| else |
| { |
| // alle dahinter verschieben in den neuen Node (this) |
| // pPrevNode->GetCharAttribs().RemoveAttrib( pAttrib ); |
| pPrevNode->GetCharAttribs().GetAttribs().Remove( nAttr ); |
| aCharAttribList.InsertAttrib( pAttrib ); |
| DBG_ASSERT( pAttrib->GetStart() >= nCut, "Start < nCut!" ); |
| DBG_ASSERT( pAttrib->GetEnd() >= nCut, "End < nCut!" ); |
| pAttrib->GetStart() = pAttrib->GetStart() - nCut; |
| pAttrib->GetEnd() = pAttrib->GetEnd() - nCut; |
| nAttr--; |
| } |
| nAttr++; |
| pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr ); |
| } |
| } |
| |
| void ContentNode::AppendAttribs( ContentNode* pNextNode ) |
| { |
| DBG_ASSERT( pNextNode, "kopieren von Attributen von einen NULL-Pointer ?" ); |
| |
| sal_uInt16 nNewStart = Len(); |
| |
| #ifdef EDITDEBUG |
| DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute VOR AppendAttribs kaputt" ); |
| #endif |
| |
| sal_uInt16 nAttr = 0; |
| EditCharAttrib* pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr ); |
| while ( pAttrib ) |
| { |
| // alle Attribute verschieben in den aktuellen Node (this) |
| sal_Bool bMelted = sal_False; |
| if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) ) |
| { |
| // Evtl koennen Attribute zusammengefasst werden: |
| sal_uInt16 nTmpAttr = 0; |
| EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); |
| while ( !bMelted && pTmpAttrib ) |
| { |
| if ( pTmpAttrib->GetEnd() == nNewStart ) |
| { |
| if ( ( pTmpAttrib->Which() == pAttrib->Which() ) && |
| ( *(pTmpAttrib->GetItem()) == *(pAttrib->GetItem() ) ) ) |
| { |
| pTmpAttrib->GetEnd() = |
| pTmpAttrib->GetEnd() + pAttrib->GetLen(); |
| pNextNode->GetCharAttribs().GetAttribs().Remove( nAttr ); |
| // Vom Pool abmelden ?! |
| delete pAttrib; |
| bMelted = sal_True; |
| } |
| } |
| ++nTmpAttr; |
| pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); |
| } |
| } |
| |
| if ( !bMelted ) |
| { |
| pAttrib->GetStart() = pAttrib->GetStart() + nNewStart; |
| pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart; |
| aCharAttribList.InsertAttrib( pAttrib ); |
| ++nAttr; |
| } |
| pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr ); |
| } |
| // Fuer die Attribute, die nur ruebergewandert sind: |
| pNextNode->GetCharAttribs().Clear(); |
| |
| #ifdef EDITDEBUG |
| DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute NACH AppendAttribs kaputt" ); |
| #endif |
| } |
| |
| void ContentNode::CreateDefFont() |
| { |
| // Erst alle Informationen aus dem Style verwenden... |
| SfxStyleSheet* pS = aContentAttribs.GetStyleSheet(); |
| if ( pS ) |
| CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() ); |
| |
| // ... dann die harte Absatzformatierung rueberbuegeln... |
| CreateFont( GetCharAttribs().GetDefFont(), |
| GetContentAttribs().GetItems(), pS == NULL ); |
| } |
| |
| void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle ) |
| { |
| aContentAttribs.SetStyleSheet( pS ); |
| |
| // Erst alle Informationen aus dem Style verwenden... |
| GetCharAttribs().GetDefFont() = rFontFromStyle; |
| // ... dann die harte Absatzformatierung rueberbuegeln... |
| CreateFont( GetCharAttribs().GetDefFont(), |
| GetContentAttribs().GetItems(), pS == NULL ); |
| } |
| |
| void ContentNode::SetStyleSheet( SfxStyleSheet* pS, sal_Bool bRecalcFont ) |
| { |
| aContentAttribs.SetStyleSheet( pS ); |
| if ( bRecalcFont ) |
| CreateDefFont(); |
| } |
| |
| void ContentNode::DestroyWrongList() |
| { |
| #ifndef SVX_LIGHT |
| delete pWrongList; |
| #endif |
| pWrongList = NULL; |
| } |
| |
| void ContentNode::CreateWrongList() |
| { |
| DBG_ASSERT( !pWrongList, "WrongList existiert schon!" ); |
| #ifndef SVX_LIGHT |
| pWrongList = new WrongList; |
| #endif |
| } |
| |
| void ContentNode::SetWrongList( WrongList* p ) |
| { |
| DBG_ASSERT( !pWrongList, "WrongList existiert schon!" ); |
| pWrongList = p; |
| } |
| |
| // ------------------------------------------------------------------------- |
| // class ContentAttribs |
| // ------------------------------------------------------------------------- |
| ContentAttribs::ContentAttribs( SfxItemPool& rPool ) : |
| aAttribSet( rPool, EE_PARA_START, EE_CHAR_END ) |
| { |
| pStyle = 0; |
| } |
| |
| ContentAttribs::ContentAttribs( const ContentAttribs& rRef ) : |
| aAttribSet( rRef.aAttribSet ) |
| { |
| pStyle = rRef.pStyle; |
| } |
| |
| ContentAttribs::~ContentAttribs() |
| { |
| } |
| |
| SvxTabStop ContentAttribs::FindTabStop( long nCurPos, sal_uInt16 nDefTab ) |
| { |
| const SvxTabStopItem& rTabs = (const SvxTabStopItem&) GetItem( EE_PARA_TABS ); |
| for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ ) |
| { |
| const SvxTabStop& rTab = rTabs[i]; |
| if ( rTab.GetTabPos() > nCurPos ) |
| return rTab; |
| } |
| |
| // DefTab ermitteln... |
| SvxTabStop aTabStop; |
| long x = nCurPos / nDefTab + 1; |
| aTabStop.GetTabPos() = nDefTab * x; |
| return aTabStop; |
| } |
| |
| void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS ) |
| { |
| sal_Bool bStyleChanged = ( pStyle != pS ); |
| pStyle = pS; |
| // #104799# Only when other style sheet, not when current style sheet modified |
| if ( pStyle && bStyleChanged ) |
| { |
| // Gezielt die Attribute aus der Absatzformatierung entfernen, die im Style |
| // spezifiziert sind, damit die Attribute des Styles wirken koennen. |
| const SfxItemSet& rStyleAttribs = pStyle->GetItemSet(); |
| for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ ) |
| { |
| // #99635# Don't change bullet on/off |
| if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON ) ) |
| aAttribSet.ClearItem( nWhich ); |
| } |
| } |
| } |
| |
| const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich ) |
| { |
| // Harte Absatzattribute haben Vorrang! |
| SfxItemSet* pTakeFrom = &aAttribSet; |
| if ( pStyle && ( aAttribSet.GetItemState( nWhich, sal_False ) != SFX_ITEM_ON ) ) |
| pTakeFrom = &pStyle->GetItemSet(); |
| |
| return pTakeFrom->Get( nWhich ); |
| } |
| |
| sal_Bool ContentAttribs::HasItem( sal_uInt16 nWhich ) |
| { |
| sal_Bool bHasItem = sal_False; |
| if ( aAttribSet.GetItemState( nWhich, sal_False ) == SFX_ITEM_ON ) |
| bHasItem = sal_True; |
| else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SFX_ITEM_ON ) |
| bHasItem = sal_True; |
| |
| return bHasItem; |
| } |
| |
| |
| |
| // ---------------------------------------------------------------------- |
| // class ItemList |
| // ---------------------------------------------------------------------- |
| const SfxPoolItem* ItemList::FindAttrib( sal_uInt16 nWhich ) |
| { |
| const SfxPoolItem* pItem = First(); |
| while ( pItem && ( pItem->Which() != nWhich ) ) |
| pItem = Next(); |
| |
| return pItem; |
| } |
| |
| // ------------------------------------------------------------------------- |
| // class EditDoc |
| // ------------------------------------------------------------------------- |
| EditDoc::EditDoc( SfxItemPool* pPool ) |
| { |
| if ( pPool ) |
| { |
| pItemPool = pPool; |
| bOwnerOfPool = sal_False; |
| } |
| else |
| { |
| pItemPool = new EditEngineItemPool( sal_False ); |
| bOwnerOfPool = sal_True; |
| } |
| |
| nDefTab = DEFTAB; |
| bIsVertical = sal_False; |
| bIsFixedCellHeight = sal_False; |
| |
| // Don't create a empty node, Clear() will be called in EditEngine-CTOR |
| |
| SetModified( sal_False ); |
| }; |
| |
| EditDoc::~EditDoc() |
| { |
| ImplDestroyContents(); |
| if ( bOwnerOfPool ) |
| SfxItemPool::Free(pItemPool); |
| } |
| |
| void EditDoc::ImplDestroyContents() |
| { |
| for ( sal_uInt16 nNode = Count(); nNode; ) |
| RemoveItemsFromPool( GetObject( --nNode ) ); |
| DeleteAndDestroy( 0, Count() ); |
| } |
| |
| void EditDoc::RemoveItemsFromPool( ContentNode* pNode ) |
| { |
| for ( sal_uInt16 nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ ) |
| { |
| EditCharAttrib* pAttr = pNode->GetCharAttribs().GetAttribs()[nAttr]; |
| GetItemPool().Remove( *pAttr->GetItem() ); |
| } |
| } |
| |
| void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, short nScriptType ) |
| { |
| Font aPrevFont( rFont ); |
| rFont.SetAlign( ALIGN_BASELINE ); |
| rFont.SetTransparent( sal_True ); |
| |
| sal_uInt16 nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ); |
| sal_uInt16 nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ); |
| sal_uInt16 nWhich_FontHeight = GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType ); |
| sal_uInt16 nWhich_Weight = GetScriptItemId( EE_CHAR_WEIGHT, nScriptType ); |
| sal_uInt16 nWhich_Italic = GetScriptItemId( EE_CHAR_ITALIC, nScriptType ); |
| |
| if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontInfo ) == SFX_ITEM_ON ) ) |
| { |
| const SvxFontItem& rFontItem = (const SvxFontItem&)rSet.Get( nWhich_FontInfo ); |
| rFont.SetName( rFontItem.GetFamilyName() ); |
| rFont.SetFamily( rFontItem.GetFamily() ); |
| rFont.SetPitch( rFontItem.GetPitch() ); |
| rFont.SetCharSet( rFontItem.GetCharSet() ); |
| } |
| if ( bSearchInParent || ( rSet.GetItemState( nWhich_Language ) == SFX_ITEM_ON ) ) |
| rFont.SetLanguage( ((const SvxLanguageItem&)rSet.Get( nWhich_Language )).GetLanguage() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SFX_ITEM_ON ) ) |
| rFont.SetColor( ((const SvxColorItem&)rSet.Get( EE_CHAR_COLOR )).GetValue() ); |
| if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SFX_ITEM_ON ) ) |
| rFont.SetSize( Size( rFont.GetSize().Width(), ((const SvxFontHeightItem&)rSet.Get( nWhich_FontHeight ) ).GetHeight() ) ); |
| if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SFX_ITEM_ON ) ) |
| rFont.SetWeight( ((const SvxWeightItem&)rSet.Get( nWhich_Weight )).GetWeight() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_UNDERLINE ) == SFX_ITEM_ON ) ) |
| rFont.SetUnderline( ((const SvxUnderlineItem&)rSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OVERLINE ) == SFX_ITEM_ON ) ) |
| rFont.SetOverline( ((const SvxOverlineItem&)rSet.Get( EE_CHAR_OVERLINE )).GetLineStyle() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_STRIKEOUT ) == SFX_ITEM_ON ) ) |
| rFont.SetStrikeout( ((const SvxCrossedOutItem&)rSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() ); |
| if ( bSearchInParent || ( rSet.GetItemState( nWhich_Italic ) == SFX_ITEM_ON ) ) |
| rFont.SetItalic( ((const SvxPostureItem&)rSet.Get( nWhich_Italic )).GetPosture() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OUTLINE ) == SFX_ITEM_ON ) ) |
| rFont.SetOutline( ((const SvxContourItem&)rSet.Get( EE_CHAR_OUTLINE )).GetValue() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_SHADOW ) == SFX_ITEM_ON ) ) |
| rFont.SetShadow( ((const SvxShadowedItem&)rSet.Get( EE_CHAR_SHADOW )).GetValue() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_ESCAPEMENT ) == SFX_ITEM_ON ) ) |
| { |
| const SvxEscapementItem& rEsc = (const SvxEscapementItem&) rSet.Get( EE_CHAR_ESCAPEMENT ); |
| |
| sal_uInt16 nProp = rEsc.GetProp(); |
| rFont.SetPropr( (sal_uInt8)nProp ); |
| |
| short nEsc = rEsc.GetEsc(); |
| if ( nEsc == DFLT_ESC_AUTO_SUPER ) |
| nEsc = 100 - nProp; |
| else if ( nEsc == DFLT_ESC_AUTO_SUB ) |
| nEsc = sal::static_int_cast< short >( -( 100 - nProp ) ); |
| rFont.SetEscapement( nEsc ); |
| } |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_PAIRKERNING ) == SFX_ITEM_ON ) ) |
| rFont.SetKerning( ((const SvxAutoKernItem&)rSet.Get( EE_CHAR_PAIRKERNING )).GetValue() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_KERNING ) == SFX_ITEM_ON ) ) |
| rFont.SetFixKerning( ((const SvxKerningItem&)rSet.Get( EE_CHAR_KERNING )).GetValue() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_WLM ) == SFX_ITEM_ON ) ) |
| rFont.SetWordLineMode( ((const SvxWordLineModeItem&)rSet.Get( EE_CHAR_WLM )).GetValue() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_EMPHASISMARK ) == SFX_ITEM_ON ) ) |
| rFont.SetEmphasisMark( ((const SvxEmphasisMarkItem&)rSet.Get( EE_CHAR_EMPHASISMARK )).GetValue() ); |
| if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_RELIEF ) == SFX_ITEM_ON ) ) |
| rFont.SetRelief( (FontRelief)((const SvxCharReliefItem&)rSet.Get( EE_CHAR_RELIEF )).GetValue() ); |
| |
| // Ob ich jetzt den ganzen Font vergleiche, oder vor jeder Aenderung |
| // pruefe, ob der Wert sich aendert, bleibt sich relativ gleich. |
| // So ggf ein MakeUniqFont im Font mehr, dafuer bei Aenderung schnellerer |
| // Abbruch der Abfrage, oder ich musste noch jedesmal ein bChanged pflegen. |
| if ( rFont == aPrevFont ) |
| rFont = aPrevFont; // => Gleicher ImpPointer fuer IsSameInstance |
| } |
| |
| void EditDoc::CreateDefFont( sal_Bool bUseStyles ) |
| { |
| SfxItemSet aTmpSet( GetItemPool(), EE_PARA_START, EE_CHAR_END ); |
| CreateFont( aDefFont, aTmpSet ); |
| aDefFont.SetVertical( IsVertical() ); |
| aDefFont.SetOrientation( IsVertical() ? 2700 : 0 ); |
| |
| for ( sal_uInt16 nNode = 0; nNode < Count(); nNode++ ) |
| { |
| ContentNode* pNode = GetObject( nNode ); |
| pNode->GetCharAttribs().GetDefFont() = aDefFont; |
| if ( bUseStyles ) |
| pNode->CreateDefFont(); |
| } |
| } |
| |
| static const sal_Unicode aCR[] = { 0x0d, 0x00 }; |
| static const sal_Unicode aLF[] = { 0x0a, 0x00 }; |
| static const sal_Unicode aCRLF[] = { 0x0d, 0x0a, 0x00 }; |
| |
| XubString EditDoc::GetSepStr( LineEnd eEnd ) |
| { |
| XubString aSep; |
| if ( eEnd == LINEEND_CR ) |
| aSep = aCR; |
| else if ( eEnd == LINEEND_LF ) |
| aSep = aLF; |
| else |
| aSep = aCRLF; |
| return aSep; |
| } |
| |
| XubString EditDoc::GetText( LineEnd eEnd ) const |
| { |
| sal_uLong nLen = GetTextLen(); |
| sal_uInt16 nNodes = Count(); |
| |
| String aSep = EditDoc::GetSepStr( eEnd ); |
| sal_uInt16 nSepSize = aSep.Len(); |
| |
| if ( nSepSize ) |
| nLen += nNodes * nSepSize; |
| if ( nLen > 0xFFFb / sizeof(xub_Unicode) ) |
| { |
| DBG_ERROR( "Text zu gross fuer String" ); |
| return XubString(); |
| } |
| xub_Unicode* pStr = new xub_Unicode[nLen+1]; |
| xub_Unicode* pCur = pStr; |
| sal_uInt16 nLastNode = nNodes-1; |
| for ( sal_uInt16 nNode = 0; nNode < nNodes; nNode++ ) |
| { |
| XubString aTmp( GetParaAsString( GetObject(nNode) ) ); |
| memcpy( pCur, aTmp.GetBuffer(), aTmp.Len()*sizeof(sal_Unicode) ); |
| pCur += aTmp.Len(); |
| if ( nSepSize && ( nNode != nLastNode ) ) |
| { |
| memcpy( pCur, aSep.GetBuffer(), nSepSize*sizeof(sal_Unicode ) ); |
| pCur += nSepSize; |
| } |
| } |
| *pCur = '\0'; |
| XubString aASCIIText( pStr ); |
| delete[] pStr; |
| return aASCIIText; |
| } |
| |
| XubString EditDoc::GetParaAsString( sal_uInt16 nNode ) const |
| { |
| return GetParaAsString( SaveGetObject( nNode ) ); |
| } |
| |
| XubString EditDoc::GetParaAsString( ContentNode* pNode, sal_uInt16 nStartPos, sal_uInt16 nEndPos, sal_Bool bResolveFields ) const |
| { |
| if ( nEndPos > pNode->Len() ) |
| nEndPos = pNode->Len(); |
| |
| DBG_ASSERT( nStartPos <= nEndPos, "Start und Ende vertauscht?" ); |
| |
| sal_uInt16 nIndex = nStartPos; |
| XubString aStr; |
| EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature( nIndex ); |
| while ( nIndex < nEndPos ) |
| { |
| sal_uInt16 nEnd = nEndPos; |
| if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) ) |
| nEnd = pNextFeature->GetStart(); |
| else |
| pNextFeature = 0; // Feature interessiert unten nicht |
| |
| DBG_ASSERT( nEnd >= nIndex, "Ende vorm Index?" ); |
| //!! beware of sub string length of -1 which is also defined as STRING_LEN and |
| //!! thus would result in adding the whole sub string up to the end of the node !! |
| if (nEnd > nIndex) |
| aStr += XubString( *pNode, nIndex, nEnd - nIndex ); |
| |
| if ( pNextFeature ) |
| { |
| switch ( pNextFeature->GetItem()->Which() ) |
| { |
| case EE_FEATURE_TAB: aStr += '\t'; |
| break; |
| case EE_FEATURE_LINEBR: aStr += '\x0A'; |
| break; |
| case EE_FEATURE_FIELD: if ( bResolveFields ) |
| aStr += ((EditCharAttribField*)pNextFeature)->GetFieldValue(); |
| break; |
| default: DBG_ERROR( "Was fuer ein Feature ?" ); |
| } |
| pNextFeature = pNode->GetCharAttribs().FindFeature( ++nEnd ); |
| } |
| nIndex = nEnd; |
| } |
| return aStr; |
| } |
| |
| sal_uLong EditDoc::GetTextLen() const |
| { |
| sal_uLong nLen = 0; |
| for ( sal_uInt16 nNode = 0; nNode < Count(); nNode++ ) |
| { |
| ContentNode* pNode = GetObject( nNode ); |
| nLen += pNode->Len(); |
| // Felder k�nnen laenger sein als der Platzhalter im Node. |
| const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs(); |
| for ( sal_uInt16 nAttr = rAttrs.Count(); nAttr; ) |
| { |
| EditCharAttrib* pAttr = rAttrs[--nAttr]; |
| if ( pAttr->Which() == EE_FEATURE_FIELD ) |
| { |
| sal_uInt16 nFieldLen = ((EditCharAttribField*)pAttr)->GetFieldValue().Len(); |
| if ( !nFieldLen ) |
| nLen--; |
| else |
| nLen += nFieldLen-1; |
| } |
| } |
| } |
| return nLen; |
| } |
| |
| EditPaM EditDoc::Clear() |
| { |
| ImplDestroyContents(); |
| |
| ContentNode* pNode = new ContentNode( GetItemPool() ); |
| Insert( pNode, 0 ); |
| |
| CreateDefFont( sal_False ); |
| |
| SetModified( sal_False ); |
| |
| EditPaM aPaM( pNode, 0 ); |
| return aPaM; |
| } |
| |
| void EditDoc::SetModified( sal_Bool b ) |
| { |
| bModified = b; |
| if ( bModified ) |
| { |
| aModifyHdl.Call( NULL ); |
| } |
| } |
| |
| EditPaM EditDoc::RemoveText() |
| { |
| // Das alte ItemSetmerken, damit z.B. im Chart Font behalten bleibt |
| ContentNode* pPrevFirstNode = GetObject(0); |
| SfxStyleSheet* pPrevStyle = pPrevFirstNode->GetStyleSheet(); |
| SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() ); |
| Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() ); |
| |
| ImplDestroyContents(); |
| |
| ContentNode* pNode = new ContentNode( GetItemPool() ); |
| Insert( pNode, 0 ); |
| |
| pNode->SetStyleSheet( pPrevStyle, sal_False ); |
| pNode->GetContentAttribs().GetItems().Set( aPrevSet ); |
| pNode->GetCharAttribs().GetDefFont() = aPrevFont; |
| |
| SetModified( sal_True ); |
| |
| EditPaM aPaM( pNode, 0 ); |
| return aPaM; |
| } |
| |
| void EditDoc::InsertText( const EditPaM& rPaM, xub_Unicode c ) |
| { |
| DBG_ASSERT( c != 0x0A, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); |
| DBG_ASSERT( c != 0x0D, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); |
| DBG_ASSERT( c != '\t', "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); |
| |
| rPaM.GetNode()->Insert( c, rPaM.GetIndex() ); |
| rPaM.GetNode()->ExpandAttribs( rPaM.GetIndex(), 1, GetItemPool() ); |
| |
| SetModified( sal_True ); |
| } |
| |
| EditPaM EditDoc::InsertText( EditPaM aPaM, const XubString& rStr ) |
| { |
| DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); |
| DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); |
| DBG_ASSERT( rStr.Search( '\t' ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); |
| DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertText1" ); |
| |
| aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() ); |
| aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.Len(), GetItemPool() ); |
| aPaM.GetIndex() = aPaM.GetIndex() + rStr.Len(); |
| |
| SetModified( sal_True ); |
| |
| return aPaM; |
| } |
| |
| EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, sal_Bool bKeepEndingAttribs ) |
| { |
| DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertParaBreak" ); |
| ContentNode* pCurNode = aPaM.GetNode(); |
| sal_uInt16 nPos = GetPos( pCurNode ); |
| XubString aStr = aPaM.GetNode()->Copy( aPaM.GetIndex() ); |
| aPaM.GetNode()->Erase( aPaM.GetIndex() ); |
| |
| // the paragraph attributes... |
| ContentAttribs aContentAttribs( aPaM.GetNode()->GetContentAttribs() ); |
| |
| // for a new paragraph we like to have the bullet/numbering visible by default |
| aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, sal_True), EE_PARA_BULLETSTATE ); |
| |
| // ContenNode-CTOR kopiert auch die Absatzattribute |
| ContentNode* pNode = new ContentNode( aStr, aContentAttribs ); |
| |
| // Den Default-Font kopieren |
| pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont(); |
| SfxStyleSheet* pStyle = aPaM.GetNode()->GetStyleSheet(); |
| if ( pStyle ) |
| { |
| XubString aFollow( pStyle->GetFollow() ); |
| if ( aFollow.Len() && ( aFollow != pStyle->GetName() ) ) |
| { |
| SfxStyleSheetBase* pNext = pStyle->GetPool().Find( aFollow, pStyle->GetFamily() ); |
| pNode->SetStyleSheet( (SfxStyleSheet*)pNext ); |
| } |
| } |
| |
| // Zeichenattribute muessen ggf. kopiert bzw gestutzt werden: |
| pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs ); |
| |
| Insert( pNode, nPos+1 ); |
| |
| SetModified( sal_True ); |
| |
| aPaM.SetNode( pNode ); |
| aPaM.SetIndex( 0 ); |
| return aPaM; |
| } |
| |
| EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem ) |
| { |
| DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertFeature" ); |
| |
| aPaM.GetNode()->Insert( CH_FEATURE, aPaM.GetIndex() ); |
| aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() ); |
| |
| // Fuer das Feature ein Feature-Attribut anlegen... |
| EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 ); |
| DBG_ASSERT( pAttrib, "Warum kann ich kein Feature anlegen ?" ); |
| aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttrib ); |
| |
| SetModified( sal_True ); |
| |
| aPaM.GetIndex()++; |
| return aPaM; |
| } |
| |
| EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight ) |
| { |
| const EditPaM aPaM( pLeft, pLeft->Len() ); |
| |
| // Erst die Attribute, da sonst nLen nicht stimmt! |
| pLeft->AppendAttribs( pRight ); |
| // Dann den Text... |
| *pLeft += *pRight; |
| |
| // der rechte verschwindet. |
| RemoveItemsFromPool( pRight ); |
| sal_uInt16 nRight = GetPos( pRight ); |
| Remove( nRight ); |
| delete pRight; |
| |
| SetModified( sal_True ); |
| |
| return aPaM; |
| } |
| |
| EditPaM EditDoc::RemoveChars( EditPaM aPaM, sal_uInt16 nChars ) |
| { |
| // Evtl. Features entfernen! |
| aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars ); |
| aPaM.GetNode()->CollapsAttribs( aPaM.GetIndex(), nChars, GetItemPool() ); |
| |
| SetModified( sal_True ); |
| |
| return aPaM; |
| } |
| |
| void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, const SfxPoolItem& rPoolItem ) |
| { |
| DBG_ASSERT( pNode, "Wohin mit dem Attribut?" ); |
| DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" ); |
| |
| // fuer Optimierung: |
| // dieses endet am Anfang der Selektion => kann erweitert werden |
| EditCharAttrib* pEndingAttrib = 0; |
| // dieses startet am Ende der Selektion => kann erweitert werden |
| EditCharAttrib* pStartingAttrib = 0; |
| |
| DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" ); |
| |
| RemoveAttribs( pNode, nStart, nEnd, pStartingAttrib, pEndingAttrib, rPoolItem.Which() ); |
| |
| if ( pStartingAttrib && pEndingAttrib && |
| ( *(pStartingAttrib->GetItem()) == rPoolItem ) && |
| ( *(pEndingAttrib->GetItem()) == rPoolItem ) ) |
| { |
| // wird ein groesses Attribut. |
| pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd(); |
| GetItemPool().Remove( *(pStartingAttrib->GetItem()) ); |
| pNode->GetCharAttribs().GetAttribs().Remove( pNode->GetCharAttribs().GetAttribs().GetPos( pStartingAttrib ) ); |
| delete pStartingAttrib; |
| } |
| else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) ) |
| pStartingAttrib->GetStart() = nStart; |
| else if ( pEndingAttrib && ( *(pEndingAttrib->GetItem()) == rPoolItem ) ) |
| pEndingAttrib->GetEnd() = nEnd; |
| else |
| InsertAttrib( rPoolItem, pNode, nStart, nEnd ); |
| |
| if ( pStartingAttrib ) |
| pNode->GetCharAttribs().ResortAttribs(); |
| |
| SetModified( sal_True ); |
| } |
| |
| sal_Bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, sal_uInt16 nWhich ) |
| { |
| EditCharAttrib* pStarting; |
| EditCharAttrib* pEnding; |
| return RemoveAttribs( pNode, nStart, nEnd, pStarting, pEnding, nWhich ); |
| } |
| |
| sal_Bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, sal_uInt16 nWhich ) |
| { |
| DBG_ASSERT( pNode, "Wohin mit dem Attribut?" ); |
| DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" ); |
| |
| // dieses endet am Anfang der Selektion => kann erweitert werden |
| rpEnding = 0; |
| // dieses startet am Ende der Selektion => kann erweitert werden |
| rpStarting = 0; |
| |
| sal_Bool bChanged = sal_False; |
| |
| DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" ); |
| |
| // ueber die Attribute iterieren... |
| sal_uInt16 nAttr = 0; |
| EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); |
| while ( pAttr ) |
| { |
| sal_Bool bRemoveAttrib = sal_False; |
| // MT 11.9.97: |
| // Ich denke dass in dieser Methode generell keine Features geloescht |
| // werden sollen. |
| // => Dann koennen die Feature-Abfragen weiter unten entfallen |
| sal_uInt16 nAttrWhich = pAttr->Which(); |
| if ( ( nAttrWhich < EE_FEATURE_START ) && ( !nWhich || ( nAttrWhich == nWhich ) ) ) |
| { |
| // Attribut beginnt in Selection |
| if ( ( pAttr->GetStart() >= nStart ) && ( pAttr->GetStart() <= nEnd ) ) |
| { |
| bChanged = sal_True; |
| if ( pAttr->GetEnd() > nEnd ) |
| { |
| pAttr->GetStart() = nEnd; // dann faengt es dahinter an |
| rpStarting = pAttr; |
| if ( nWhich ) |
| break; // es kann kein weiteres Attrib hier liegen |
| } |
| else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) ) |
| { |
| // Feature nur loeschen, wenn genau an der Stelle |
| bRemoveAttrib = sal_True; |
| } |
| } |
| |
| // Attribut endet in Selection |
| else if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetEnd() <= nEnd ) ) |
| { |
| bChanged = sal_True; |
| if ( ( pAttr->GetStart() < nStart ) && !pAttr->IsFeature() ) |
| { |
| pAttr->GetEnd() = nStart; // dann hoert es hier auf |
| rpEnding = pAttr; |
| } |
| else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) ) |
| { |
| // Feature nur loeschen, wenn genau an der Stelle |
| bRemoveAttrib = sal_True; |
| } |
| } |
| // Attribut ueberlappt die Selektion |
| else if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) ) |
| { |
| bChanged = sal_True; |
| if ( pAttr->GetStart() == nStart ) |
| { |
| pAttr->GetStart() = nEnd; |
| rpStarting = pAttr; |
| if ( nWhich ) |
| break; // es kann weitere Attribute geben! |
| } |
| else if ( pAttr->GetEnd() == nEnd ) |
| { |
| pAttr->GetEnd() = nStart; |
| rpEnding = pAttr; |
| if ( nWhich ) |
| break; // es kann weitere Attribute geben! |
| } |
| else // Attribut muss gesplittet werden... |
| { |
| sal_uInt16 nOldEnd = pAttr->GetEnd(); |
| pAttr->GetEnd() = nStart; |
| rpEnding = pAttr; |
| InsertAttrib( *pAttr->GetItem(), pNode, nEnd, nOldEnd ); |
| if ( nWhich ) |
| break; // es kann weitere Attribute geben! |
| } |
| } |
| } |
| if ( bRemoveAttrib ) |
| { |
| DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Loeschen und behalten des gleichen Attributs ?" ); |
| DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" ); |
| pNode->GetCharAttribs().GetAttribs().Remove(nAttr); |
| GetItemPool().Remove( *pAttr->GetItem() ); |
| delete pAttr; |
| nAttr--; |
| } |
| nAttr++; |
| pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); |
| } |
| |
| if ( bChanged ) |
| { |
| // char attributes need to be sorted by start again |
| pNode->GetCharAttribs().ResortAttribs(); |
| |
| SetModified( sal_True ); |
| } |
| |
| return bChanged; |
| } |
| |
| void EditDoc::InsertAttrib( const SfxPoolItem& rPoolItem, ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd ) |
| { |
| // Diese Methode prueft nicht mehr, ob ein entspr. Attribut |
| // schon an der Stelle existiert! |
| |
| EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rPoolItem, nStart, nEnd ); |
| DBG_ASSERT( pAttrib, "MakeCharAttrib fehlgeschlagen!" ); |
| pNode->GetCharAttribs().InsertAttrib( pAttrib ); |
| |
| SetModified( sal_True ); |
| } |
| |
| void EditDoc::InsertAttrib( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, const SfxPoolItem& rPoolItem ) |
| { |
| if ( nStart != nEnd ) |
| { |
| InsertAttribInSelection( pNode, nStart, nEnd, rPoolItem ); |
| } |
| else |
| { |
| // Pruefen, ob schon ein neues Attribut mit der WhichId an der Stelle: |
| EditCharAttrib* pAttr = pNode->GetCharAttribs().FindEmptyAttrib( rPoolItem.Which(), nStart ); |
| if ( pAttr ) |
| { |
| // Attribut entfernen.... |
| pNode->GetCharAttribs().GetAttribs().Remove( |
| pNode->GetCharAttribs().GetAttribs().GetPos( pAttr ) ); |
| delete pAttr; // #i120865#, need free it explicitly |
| } |
| |
| // pruefen, ob ein 'gleiches' Attribut an der Stelle liegt. |
| pAttr = pNode->GetCharAttribs().FindAttrib( rPoolItem.Which(), nStart ); |
| if ( pAttr ) |
| { |
| if ( pAttr->IsInside( nStart ) ) // splitten |
| { |
| // ??????????????????????????????? |
| // eigentlich noch pruefen, ob wirklich splittet, oder return ! |
| // ??????????????????????????????? |
| sal_uInt16 nOldEnd = pAttr->GetEnd(); |
| pAttr->GetEnd() = nStart; |
| pAttr = MakeCharAttrib( GetItemPool(), *(pAttr->GetItem()), nStart, nOldEnd ); |
| pNode->GetCharAttribs().InsertAttrib( pAttr ); |
| } |
| else if ( pAttr->GetEnd() == nStart ) |
| { |
| DBG_ASSERT( !pAttr->IsEmpty(), "Doch noch ein leeres Attribut?" ); |
| // pruefen, ob genau das gleiche Attribut |
| if ( *(pAttr->GetItem()) == rPoolItem ) |
| return; |
| } |
| } |
| InsertAttrib( rPoolItem, pNode, nStart, nStart ); |
| } |
| |
| SetModified( sal_True ); |
| } |
| |
| void EditDoc::FindAttribs( ContentNode* pNode, sal_uInt16 nStartPos, sal_uInt16 nEndPos, SfxItemSet& rCurSet ) |
| { |
| DBG_ASSERT( pNode, "Wo soll ich suchen ?" ); |
| DBG_ASSERT( nStartPos <= nEndPos, "Ungueltiger Bereich!" ); |
| |
| sal_uInt16 nAttr = 0; |
| EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); |
| // keine Selection... |
| if ( nStartPos == nEndPos ) |
| { |
| while ( pAttr && ( pAttr->GetStart() <= nEndPos) ) |
| { |
| const SfxPoolItem* pItem = 0; |
| // Attribut liegt dadrueber... |
| if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() > nStartPos ) ) |
| pItem = pAttr->GetItem(); |
| // Attribut endet hier, ist nicht leer |
| else if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() == nStartPos ) ) |
| { |
| if ( !pNode->GetCharAttribs().FindEmptyAttrib( pAttr->GetItem()->Which(), nStartPos ) ) |
| pItem = pAttr->GetItem(); |
| } |
| // Attribut endet hier, ist leer |
| else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() == nStartPos ) ) |
| { |
| pItem = pAttr->GetItem(); |
| } |
| // Attribut beginnt hier |
| else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() > nStartPos ) ) |
| { |
| if ( nStartPos == 0 ) // Sonderfall |
| pItem = pAttr->GetItem(); |
| } |
| |
| if ( pItem ) |
| { |
| sal_uInt16 nWhich = pItem->Which(); |
| if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF ) |
| { |
| rCurSet.Put( *pItem ); |
| } |
| else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON ) |
| { |
| const SfxPoolItem& rItem = rCurSet.Get( nWhich ); |
| if ( rItem != *pItem ) |
| { |
| rCurSet.InvalidateItem( nWhich ); |
| } |
| } |
| } |
| nAttr++; |
| pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); |
| } |
| } |
| else // Selektion |
| { |
| while ( pAttr && ( pAttr->GetStart() < nEndPos) ) |
| { |
| const SfxPoolItem* pItem = 0; |
| // Attribut liegt dadrueber... |
| if ( ( pAttr->GetStart() <= nStartPos ) && ( pAttr->GetEnd() >= nEndPos ) ) |
| pItem = pAttr->GetItem(); |
| // Attribut startet mitten drin... |
| else if ( pAttr->GetStart() >= nStartPos ) |
| { |
| // !!! pItem = pAttr->GetItem(); |
| // einfach nur pItem reicht nicht, da ich z.B. bei Shadow |
| // niemals ein ungleiches Item finden wuerde, da ein solche |
| // seine Anwesenheit durch Abwesenheit repraesentiert! |
| // if ( ... ) |
| // Es muesste geprueft werden, on genau das gleiche Attribut |
| // an der Bruchstelle aufsetzt, was recht aufwendig ist. |
| // Da ich beim Einfuegen von Attributen aber etwas optimiere |
| // tritt der Fall nicht so schnell auf... |
| // Also aus Geschwindigkeitsgruenden: |
| rCurSet.InvalidateItem( pAttr->GetItem()->Which() ); |
| |
| } |
| // Attribut endet mitten drin... |
| else if ( pAttr->GetEnd() > nStartPos ) |
| { |
| // pItem = pAttr->GetItem(); |
| // s.o. |
| /*-----------------31.05.95 16:01------------------- |
| Ist falsch, wenn das gleiche Attribut sofort wieder |
| eingestellt wird! |
| => Sollte am besten nicht vorkommen, also gleich beim |
| Setzen von Attributen richtig machen! |
| --------------------------------------------------*/ |
| rCurSet.InvalidateItem( pAttr->GetItem()->Which() ); |
| } |
| |
| if ( pItem ) |
| { |
| sal_uInt16 nWhich = pItem->Which(); |
| if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF ) |
| { |
| rCurSet.Put( *pItem ); |
| } |
| else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON ) |
| { |
| const SfxPoolItem& rItem = rCurSet.Get( nWhich ); |
| if ( rItem != *pItem ) |
| { |
| rCurSet.InvalidateItem( nWhich ); |
| } |
| } |
| } |
| nAttr++; |
| pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); |
| } |
| } |
| } |
| |
| |
| // ------------------------------------------------------------------------- |
| // class EditCharAttribList |
| // ------------------------------------------------------------------------- |
| |
| CharAttribList::CharAttribList() |
| { |
| DBG_CTOR( EE_CharAttribList, 0 ); |
| bHasEmptyAttribs = sal_False; |
| } |
| |
| CharAttribList::~CharAttribList() |
| { |
| DBG_DTOR( EE_CharAttribList, 0 ); |
| |
| sal_uInt16 nAttr = 0; |
| EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); |
| while ( pAttr ) |
| { |
| delete pAttr; |
| ++nAttr; |
| pAttr = GetAttrib( aAttribs, nAttr ); |
| } |
| Clear(); |
| } |
| |
| void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib ) |
| { |
| // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
| // optimieren: binaere Suche ? ! |
| // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
| |
| // MT: 26.11.98 |
| // Vielleicht aber auch einfach nur rueckwaerts iterieren: |
| // Der haeufigste und kritischste Fall: Attribute kommen bereits |
| // sortiert an (InsertBinTextObject!) |
| // Hier waere auch binaere Suche nicht optimal. |
| // => Wuerde einiges bringen! |
| |
| const sal_uInt16 nCount = Count(); |
| const sal_uInt16 nStart = pAttrib->GetStart(); // vielleicht besser fuer Comp.Opt. |
| |
| if ( pAttrib->IsEmpty() ) |
| bHasEmptyAttribs = sal_True; |
| |
| sal_Bool bInserted = sal_False; |
| for ( sal_uInt16 x = 0; x < nCount; x++ ) |
| { |
| EditCharAttribPtr pCurAttrib = aAttribs[x]; |
| if ( pCurAttrib->GetStart() > nStart ) |
| { |
| aAttribs.Insert( pAttrib, x ); |
| bInserted = sal_True; |
| break; |
| } |
| } |
| if ( !bInserted ) |
| aAttribs.Insert( pAttrib, nCount ); |
| } |
| |
| void CharAttribList::ResortAttribs() |
| { |
| if ( Count() ) |
| { |
| #if defined __SUNPRO_CC |
| #pragma disable_warn |
| #endif |
| qsort( (void*)aAttribs.GetData(), aAttribs.Count(), sizeof( EditCharAttrib* ), CompareStart ); |
| #if defined __SUNPRO_CC |
| #pragma enable_warn |
| #endif |
| } |
| } |
| |
| void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool ) |
| { |
| for ( sal_uInt16 n = 0; n < aAttribs.Count(); n++ ) |
| { |
| EditCharAttrib* pAttr = aAttribs.GetObject( n ); |
| for ( sal_uInt16 nNext = n+1; nNext < aAttribs.Count(); nNext++ ) |
| { |
| EditCharAttrib* p = aAttribs.GetObject( nNext ); |
| if ( !pAttr->IsFeature() && ( p->GetStart() == pAttr->GetEnd() ) && ( p->Which() == pAttr->Which() ) ) |
| { |
| if ( *p->GetItem() == *pAttr->GetItem() ) |
| { |
| pAttr->GetEnd() = p->GetEnd(); |
| aAttribs.Remove( nNext ); |
| rItemPool.Remove( *p->GetItem() ); |
| delete p; |
| } |
| break; // only 1 attr with same which can start here. |
| } |
| else if ( p->GetStart() > pAttr->GetEnd() ) |
| { |
| break; |
| } |
| } |
| } |
| } |
| |
| EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) |
| { |
| // Rueckwaerts, falls eins dort endet, das naechste startet. |
| // => Das startende gilt... |
| sal_uInt16 nAttr = aAttribs.Count()-1; |
| EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); |
| while ( pAttr ) |
| { |
| if ( ( pAttr->Which() == nWhich ) && pAttr->IsIn(nPos) ) |
| return pAttr; |
| pAttr = GetAttrib( aAttribs, --nAttr ); |
| } |
| return 0; |
| } |
| |
| EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_uInt16 nFromPos ) const |
| { |
| DBG_ASSERT( nWhich, "FindNextAttrib: Which?" ); |
| const sal_uInt16 nAttribs = aAttribs.Count(); |
| for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) |
| { |
| EditCharAttrib* pAttr = aAttribs[ nAttr ]; |
| if ( ( pAttr->GetStart() >= nFromPos ) && ( pAttr->Which() == nWhich ) ) |
| return pAttr; |
| } |
| return 0; |
| } |
| |
| sal_Bool CharAttribList::HasAttrib( sal_uInt16 nWhich ) const |
| { |
| for ( sal_uInt16 nAttr = aAttribs.Count(); nAttr; ) |
| { |
| const EditCharAttrib* pAttr = aAttribs[--nAttr]; |
| if ( pAttr->Which() == nWhich ) |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| sal_Bool CharAttribList::HasAttrib( sal_uInt16 nStartPos, sal_uInt16 nEndPos ) const |
| { |
| sal_Bool bAttr = sal_False; |
| for ( sal_uInt16 nAttr = aAttribs.Count(); nAttr && !bAttr; ) |
| { |
| const EditCharAttrib* pAttr = aAttribs[--nAttr]; |
| if ( ( pAttr->GetStart() < nEndPos ) && ( pAttr->GetEnd() > nStartPos ) ) |
| return bAttr = sal_True; |
| } |
| return bAttr; |
| } |
| |
| |
| sal_Bool CharAttribList::HasBoundingAttrib( sal_uInt16 nBound ) |
| { |
| // Rueckwaerts, falls eins dort endet, das naechste startet. |
| // => Das startende gilt... |
| sal_uInt16 nAttr = aAttribs.Count()-1; |
| EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); |
| while ( pAttr && ( pAttr->GetEnd() >= nBound ) ) |
| { |
| if ( ( pAttr->GetStart() == nBound ) || ( pAttr->GetEnd() == nBound ) ) |
| return sal_True; |
| pAttr = GetAttrib( aAttribs, --nAttr ); |
| } |
| return sal_False; |
| } |
| |
| EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) |
| { |
| if ( !bHasEmptyAttribs ) |
| return 0; |
| sal_uInt16 nAttr = 0; |
| EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); |
| while ( pAttr && ( pAttr->GetStart() <= nPos ) ) |
| { |
| if ( ( pAttr->GetStart() == nPos ) && ( pAttr->GetEnd() == nPos ) && ( pAttr->Which() == nWhich ) ) |
| return pAttr; |
| nAttr++; |
| pAttr = GetAttrib( aAttribs, nAttr ); |
| } |
| return 0; |
| } |
| |
| EditCharAttrib* CharAttribList::FindFeature( sal_uInt16 nPos ) const |
| { |
| |
| sal_uInt16 nAttr = 0; |
| EditCharAttrib* pNextAttrib = GetAttrib( aAttribs, nAttr ); |
| |
| // erstmal zur gewuenschten Position... |
| while ( pNextAttrib && ( pNextAttrib->GetStart() < nPos ) ) |
| { |
| nAttr++; |
| pNextAttrib = GetAttrib( aAttribs, nAttr ); |
| } |
| |
| // jetzt das Feature suchen... |
| while ( pNextAttrib && !pNextAttrib->IsFeature() ) |
| { |
| nAttr++; |
| pNextAttrib = GetAttrib( aAttribs, nAttr ); |
| } |
| |
| return pNextAttrib; |
| } |
| |
| |
| void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool ) |
| { |
| for ( sal_uInt16 nAttr = 0; nAttr < aAttribs.Count(); nAttr++ ) |
| { |
| EditCharAttrib* pAttr = aAttribs[nAttr]; |
| if ( pAttr->IsEmpty() ) |
| { |
| rItemPool.Remove( *pAttr->GetItem() ); |
| aAttribs.Remove( nAttr ); |
| delete pAttr; |
| nAttr--; |
| } |
| } |
| bHasEmptyAttribs = sal_False; |
| } |
| |
| sal_Bool CharAttribList::DbgCheckAttribs() |
| { |
| #ifdef DBG_UTIL |
| sal_Bool bOK = sal_True; |
| for ( sal_uInt16 nAttr = 0; nAttr < aAttribs.Count(); nAttr++ ) |
| { |
| EditCharAttrib* pAttr = aAttribs[nAttr]; |
| if ( pAttr->GetStart() > pAttr->GetEnd() ) |
| { |
| bOK = sal_False; |
| DBG_ERROR( "Attr verdreht" ); |
| } |
| else if ( pAttr->IsFeature() && ( pAttr->GetLen() != 1 ) ) |
| { |
| bOK = sal_False; |
| DBG_ERROR( "Feature, Len != 1" ); |
| } |
| } |
| return bOK; |
| #else |
| return sal_True; |
| #endif |
| } |
| |
| |
| |
| SvxFontTable::SvxFontTable() |
| { |
| } |
| |
| SvxFontTable::~SvxFontTable() |
| { |
| SvxFontItem* pItem = First(); |
| while( pItem ) |
| { |
| delete pItem; |
| pItem = Next(); |
| } |
| } |
| |
| sal_uLong SvxFontTable::GetId( const SvxFontItem& rFontItem ) |
| { |
| SvxFontItem* pItem = First(); |
| while ( pItem ) |
| { |
| if ( *pItem == rFontItem ) |
| return GetCurKey(); |
| pItem = Next(); |
| } |
| DBG_WARNING( "Font nicht gefunden: GetId()" ); |
| return 0; |
| } |
| |
| SvxColorList::SvxColorList() |
| { |
| } |
| |
| SvxColorList::~SvxColorList() |
| { |
| SvxColorItem* pItem = First(); |
| while( pItem ) |
| { |
| delete pItem; |
| pItem = Next(); |
| } |
| } |
| |
| sal_uLong SvxColorList::GetId( const SvxColorItem& rColorItem ) |
| { |
| SvxColorItem* pItem = First(); |
| while ( pItem ) |
| { |
| if ( *pItem == rColorItem ) |
| return GetCurPos(); |
| pItem = Next(); |
| } |
| DBG_WARNING( "Color nicht gefunden: GetId()" ); |
| return 0; |
| } |
| |
| EditEngineItemPool::EditEngineItemPool( sal_Bool bPersistenRefCounts ) |
| : SfxItemPool( String( "EditEngineItemPool", RTL_TEXTENCODING_ASCII_US ), EE_ITEMS_START, EE_ITEMS_END, |
| aItemInfos, 0, bPersistenRefCounts ) |
| { |
| SetVersionMap( 1, 3999, 4015, aV1Map ); |
| SetVersionMap( 2, 3999, 4019, aV2Map ); |
| SetVersionMap( 3, 3997, 4020, aV3Map ); |
| SetVersionMap( 4, 3994, 4022, aV4Map ); |
| SetVersionMap( 5, 3994, 4037, aV5Map ); |
| |
| DBG_ASSERT( EE_DLL(), "EditDLL?!" ); |
| SfxPoolItem** ppDefItems = EE_DLL()->GetGlobalData()->GetDefItems(); |
| SetDefaults( ppDefItems ); |
| } |
| |
| EditEngineItemPool::~EditEngineItemPool() |
| { |
| } |
| |
| SvStream& EditEngineItemPool::Store( SvStream& rStream ) const |
| { |
| // Bei einem 3.1-Export muess ein Hack eingebaut werden, da BUG im |
| // SfxItemSet::Load, aber nicht nachtraeglich in 3.1 fixbar. |
| |
| // Der eingestellte Range muss nach Store erhalten bleiben, weil dann |
| // erst die ItemSets gespeichert werden... |
| |
| long nVersion = rStream.GetVersion(); |
| sal_Bool b31Format = ( nVersion && ( nVersion <= SOFFICE_FILEFORMAT_31 ) ) |
| ? sal_True : sal_False; |
| |
| EditEngineItemPool* pThis = (EditEngineItemPool*)this; |
| if ( b31Format ) |
| pThis->SetStoringRange( 3997, 4022 ); |
| else |
| pThis->SetStoringRange( EE_ITEMS_START, EE_ITEMS_END ); |
| |
| return SfxItemPool::Store( rStream ); |
| } |