summaryrefslogtreecommitdiff
path: root/sw/source/core/txtnode/ndtxt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/txtnode/ndtxt.cxx')
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx4992
1 files changed, 4992 insertions, 0 deletions
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
new file mode 100644
index 000000000000..ee4b26e4ee03
--- /dev/null
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -0,0 +1,4992 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ndtxt.cxx,v $
+ * $Revision: 1.86.66.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <hints.hxx>
+
+#include <svx/fontitem.hxx>
+#include <svx/brkitem.hxx>
+#include <svx/escpitem.hxx>
+#include <svx/lrspitem.hxx>
+// --> OD 2008-01-17 #newlistlevelattrs#
+#include <svx/tstpitem.hxx>
+// <--
+#include <svl/urihelper.hxx>
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+#endif
+#include <svl/ctloptions.hxx>
+#include <swmodule.hxx>
+#include <txtfld.hxx>
+#include <txtinet.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtpdsc.hxx>
+#include <txtatr.hxx>
+#include <fmtrfmrk.hxx>
+#include <txttxmrk.hxx>
+#include <fchrfmt.hxx>
+#include <txtftn.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtfld.hxx>
+#include <frmatr.hxx>
+#include <charatr.hxx>
+#include <ftnidx.hxx>
+#include <ftninfo.hxx>
+#include <fmtftn.hxx>
+#include <fmtmeta.hxx>
+#include <charfmt.hxx>
+#include <ndtxt.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <pam.hxx> // fuer SwPosition
+#include <fldbas.hxx>
+#include <errhdl.hxx>
+#include <paratr.hxx>
+#include <txtfrm.hxx>
+#include <ftnfrm.hxx>
+#include <ftnboss.hxx>
+#include <rootfrm.hxx>
+#include <pagedesc.hxx> // fuer SwPageDesc
+#include <expfld.hxx> // fuer SwTblField
+#include <section.hxx> // fuer SwSection
+#include <mvsave.hxx>
+#include <swcache.hxx>
+#include <SwGrammarMarkUp.hxx>
+#include <dcontact.hxx>
+#include <redline.hxx>
+#include <doctxm.hxx>
+#include <IMark.hxx>
+#include <scriptinfo.hxx>
+#include <istyleaccess.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <numrule.hxx>
+
+//--> #outlinelevel added by zhaojianwei
+#include <svl/intitem.hxx>
+//<--end
+#include <swtable.hxx>
+#include <docsh.hxx>
+#include <SwNodeNum.hxx>
+// --> OD 2008-02-25 #refactorlists#
+#include <svl/intitem.hxx>
+#include <list.hxx>
+// <--
+
+SV_DECL_PTRARR( TmpHints, SwTxtAttr*, 0, 4 )
+
+TYPEINIT1( SwTxtNode, SwCntntNode )
+
+SV_DECL_PTRARR(SwpHts,SwTxtAttr*,1,1)
+
+// Leider ist das SwpHints nicht ganz wasserdicht:
+// Jeder darf an den Hints rumfummeln, ohne die Sortierreihenfolge
+// und Verkettung sicherstellen zu muessen.
+#ifdef DBG_UTIL
+#define CHECK_SWPHINTS(pNd) { if( pNd->GetpSwpHints() && \
+ !pNd->GetDoc()->IsInReading() ) \
+ pNd->GetpSwpHints()->Check(); }
+#else
+#define CHECK_SWPHINTS(pNd)
+#endif
+
+SwTxtNode *SwNodes::MakeTxtNode( const SwNodeIndex & rWhere,
+ SwTxtFmtColl *pColl,
+ SwAttrSet* pAutoAttr )
+{
+ ASSERT( pColl, "Collectionpointer ist 0." );
+
+ SwTxtNode *pNode = new SwTxtNode( rWhere, pColl, pAutoAttr );
+
+ SwNodeIndex aIdx( *pNode );
+
+ // --> OD 2005-11-03 #125329#
+ // call method <UpdateOutlineNode(..)> only for the document nodes array
+ if ( IsDocNodes() )
+ {
+ //if ( pColl && NO_NUMBERING != pColl->GetOutlineLevel() ) //#outline level,removed by zhaojianwei
+ //{
+ // UpdateOutlineNode( *pNode, NO_NUMBERING, pColl->GetOutlineLevel() );
+ //}
+// if ( pColl && 0 != pColl->GetAttrOutlineLevel() )//#outline level,added by zhaojianwei
+// {
+// UpdateOutlineNode( *pNode, 0, pColl->GetAttrOutlineLevel() );
+// }//<--end
+// else
+ {
+ UpdateOutlineNode(*pNode);
+ }
+ }
+ // <--
+
+ //Wenn es noch kein Layout gibt oder in einer versteckten Section
+ // stehen, brauchen wir uns um das MakeFrms nicht bemuehen.
+ const SwSectionNode* pSectNd;
+ if( !GetDoc()->GetRootFrm() ||
+ ( 0 != (pSectNd = pNode->FindSectionNode()) &&
+ pSectNd->GetSection().IsHiddenFlag() ))
+ return pNode;
+
+ SwNodeIndex aTmp( rWhere );
+ do {
+ // max. 2 Durchlaeufe:
+ // 1. den Nachfolger nehmen
+ // 2. den Vorgaenger
+
+ SwNode *pNd;
+ switch( ( pNd = (*this)[aTmp] )->GetNodeType() )
+ {
+ case ND_TABLENODE:
+ ((SwTableNode*)pNd)->MakeFrms( aIdx );
+ return pNode;
+
+ case ND_SECTIONNODE:
+ if( ((SwSectionNode*)pNd)->GetSection().IsHidden() ||
+ ((SwSectionNode*)pNd)->IsCntntHidden() )
+ {
+ SwNodeIndex aTmpIdx( *pNode );
+ pNd = FindPrvNxtFrmNode( aTmpIdx, pNode );
+ if( !pNd )
+ return pNode;
+ aTmp = *pNd;
+ break;
+ }
+ ((SwSectionNode*)pNd)->MakeFrms( aIdx );
+ return pNode;
+
+ case ND_TEXTNODE:
+ case ND_GRFNODE:
+ case ND_OLENODE:
+ ((SwCntntNode*)pNd)->MakeFrms( *pNode );
+ return pNode;
+
+ case ND_ENDNODE:
+ if( pNd->StartOfSectionNode()->IsSectionNode() &&
+ aTmp.GetIndex() < rWhere.GetIndex() )
+ {
+ if( pNd->StartOfSectionNode()->GetSectionNode()->GetSection().IsHiddenFlag())
+ {
+ if( !GoPrevSection( &aTmp, TRUE, FALSE ) ||
+ aTmp.GetNode().FindTableNode() !=
+ pNode->FindTableNode() )
+ return pNode; // schade, das wars
+ }
+ else
+ aTmp = *pNd->StartOfSectionNode();
+ break;
+ }
+ else if( pNd->StartOfSectionNode()->IsTableNode() &&
+ aTmp.GetIndex() < rWhere.GetIndex() )
+ {
+ // wir stehen hinter einem TabellenNode
+ aTmp = *pNd->StartOfSectionNode();
+ break;
+ }
+ // kein break !!!
+ default:
+ if( rWhere == aTmp )
+ aTmp -= 2;
+ else
+ return pNode;
+ break;
+ }
+ } while( TRUE );
+}
+
+// --------------------
+// SwTxtNode
+// --------------------
+
+SwTxtNode::SwTxtNode( const SwNodeIndex &rWhere,
+ SwTxtFmtColl *pTxtColl,
+ const SfxItemSet* pAutoAttr )
+ : SwCntntNode( rWhere, ND_TEXTNODE, pTxtColl ),
+ m_pSwpHints( 0 ),
+ mpNodeNum( 0 ),
+ m_bLastOutlineState( false ),
+ m_bNotifiable( false ),
+ // --> OD 2008-11-19 #i70748#
+ mbEmptyListStyleSetDueToSetOutlineLevelAttr( false ),
+ // <--
+ // --> OD 2008-05-06 #refactorlists#
+ mbInSetOrResetAttr( false ),
+ mpList( 0 )
+ // <--
+{
+ InitSwParaStatistics( true );
+
+ // soll eine Harte-Attributierung gesetzt werden?
+ if( pAutoAttr )
+ SetAttr( *pAutoAttr );
+
+ // --> OD 2008-03-13 #refactorlists# - no longed needed
+// SyncNumberAndNumRule();
+ if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
+ {
+ // --> OD 2009-08-27 #i101516#
+ // apply paragraph style's assigned outline style list level as
+ // list level of the paragraph, if it has none set already.
+ if ( !HasAttrListLevel() &&
+ pTxtColl && pTxtColl->IsAssignedToListLevelOfOutlineStyle() )
+ {
+ SetAttrListLevel( pTxtColl->GetAssignedOutlineStyleLevel() );
+ }
+ // <--
+ AddToList();
+ }
+ // <--
+ GetNodes().UpdateOutlineNode(*this);
+
+ m_bNotifiable = true;
+
+ m_bContainsHiddenChars = m_bHiddenCharsHidePara = false;
+ m_bRecalcHiddenCharFlags = true;
+}
+
+SwTxtNode::~SwTxtNode()
+{
+ // delete loescht nur die Pointer, nicht die Arrayelemente!
+ if ( m_pSwpHints )
+ {
+ // damit Attribute die ihren Inhalt entfernen nicht doppelt
+ // geloescht werden.
+ SwpHints* pTmpHints = m_pSwpHints;
+ m_pSwpHints = 0;
+
+ for( USHORT j = pTmpHints->Count(); j; )
+ // erst muss das Attribut aus dem Array entfernt werden,
+ // denn sonst wuerde es sich selbst loeschen (Felder) !!!!
+ DestroyAttr( pTmpHints->GetTextHint( --j ) );
+
+ delete pTmpHints;
+ }
+
+ // --> OD 2008-03-13 #refactorlists#
+// if ( mpNodeNum )
+// {
+// mpNodeNum->RemoveMe();
+// delete mpNodeNum;
+// mpNodeNum = 0L;
+// }
+ RemoveFromList();
+ // <--
+
+ InitSwParaStatistics( false );
+}
+
+SwCntntFrm *SwTxtNode::MakeFrm()
+{
+ SwCntntFrm *pFrm = new SwTxtFrm(this);
+ return pFrm;
+}
+
+xub_StrLen SwTxtNode::Len() const
+{
+ return m_Text.Len();
+}
+
+/*---------------------------------------------------------------------------
+ * lcl_ChangeFtnRef
+ * After a split node, it's necessary to actualize the ref-pointer of the
+ * ftnfrms.
+ * --------------------------------------------------------------------------*/
+
+void lcl_ChangeFtnRef( SwTxtNode &rNode )
+{
+ SwpHints *pSwpHints = rNode.GetpSwpHints();
+ if( pSwpHints && rNode.GetDoc()->GetRootFrm() )
+ {
+ SwTxtAttr* pHt;
+ SwCntntFrm* pFrm = NULL;
+ // OD 07.11.2002 #104840# - local variable to remember first footnote
+ // of node <rNode> in order to invalidate position of its first content.
+ // Thus, in its <MakeAll()> it will checked its position relative to its reference.
+ SwFtnFrm* pFirstFtnOfNode = 0;
+ for( USHORT j = pSwpHints->Count(); j; )
+ {
+ pHt = pSwpHints->GetTextHint(--j);
+ if (RES_TXTATR_FTN == pHt->Which())
+ {
+ if( !pFrm )
+ {
+ SwClientIter aNew( rNode );
+ pFrm = (SwCntntFrm*)aNew.First( TYPE(SwCntntFrm) );
+ if( !pFrm )
+ return;
+ }
+ SwTxtFtn *pAttr = (SwTxtFtn*)pHt;
+ ASSERT( pAttr->GetStartNode(), "FtnAtr ohne StartNode." );
+ SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
+ SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
+ if ( !pNd )
+ pNd = pFrm->GetAttrSet()->GetDoc()->
+ GetNodes().GoNextSection( &aIdx, TRUE, FALSE );
+ if ( !pNd )
+ continue;
+ SwClientIter aIter( *pNd );
+ SwCntntFrm* pCntnt = (SwCntntFrm*)aIter.First(TYPE(SwCntntFrm));
+ if( pCntnt )
+ {
+ ASSERT( pCntnt->FindRootFrm() == pFrm->FindRootFrm(),
+ "lcl_ChangeFtnRef: Layout double?" );
+ SwFtnFrm *pFtn = pCntnt->FindFtnFrm();
+ if( pFtn && pFtn->GetAttr() == pAttr )
+ {
+ while( pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ // OD 07.11.2002 #104840# - remember footnote frame
+ pFirstFtnOfNode = pFtn;
+ while ( pFtn )
+ {
+ pFtn->SetRef( pFrm );
+ pFtn = pFtn->GetFollow();
+ ((SwTxtFrm*)pFrm)->SetFtn( TRUE );
+ }
+ }
+#ifdef DBG_UTIL
+ while( 0 != (pCntnt = (SwCntntFrm*)aIter.Next()) )
+ {
+ SwFtnFrm *pDbgFtn = pCntnt->FindFtnFrm();
+ ASSERT( !pDbgFtn || pDbgFtn->GetRef() == pFrm,
+ "lcl_ChangeFtnRef: Who's that guy?" );
+ }
+#endif
+ }
+ }
+ } // end of for-loop on <SwpHints>
+ // OD 08.11.2002 #104840# - invalidate
+ if ( pFirstFtnOfNode )
+ {
+ SwCntntFrm* pCntnt = pFirstFtnOfNode->ContainsCntnt();
+ if ( pCntnt )
+ {
+ pCntnt->_InvalidatePos();
+ }
+ }
+ }
+}
+
+SwCntntNode *SwTxtNode::SplitCntntNode( const SwPosition &rPos )
+{
+ // lege den Node "vor" mir an
+ const xub_StrLen nSplitPos = rPos.nContent.GetIndex();
+ const xub_StrLen nTxtLen = m_Text.Len();
+ SwTxtNode* const pNode =
+ _MakeNewTxtNode( rPos.nNode, FALSE, nSplitPos==nTxtLen );
+
+ // the first paragraph gets the XmlId,
+ // _except_ if it is empty and the second is not empty
+ if (nSplitPos != 0) {
+ pNode->RegisterAsCopyOf(*this, true);
+ if (nSplitPos == nTxtLen)
+ {
+ this->RemoveMetadataReference();
+ // NB: SwUndoSplitNode will call pNode->JoinNext,
+ // which is sufficient even in this case!
+ }
+ }
+
+ // --> OD 2008-03-27 #refactorlists#
+// // --> OD 2007-07-09 #i77372#
+// // reset numbering attribute at current node, only if it is numbered.
+// if ( GetNumRule() != NULL )
+// {
+// SetRestart(false);
+// SetStart(1);
+// SetCounted(true);
+// }
+ ResetAttr( RES_PARATR_LIST_ISRESTART );
+ ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
+ ResetAttr( RES_PARATR_LIST_ISCOUNTED );
+ if ( GetNumRule() == 0 )
+ {
+ ResetAttr( RES_PARATR_LIST_ID );
+ ResetAttr( RES_PARATR_LIST_LEVEL );
+ }
+ // <--
+
+ if ( GetDepends() && m_Text.Len() && (nTxtLen / 2) < nSplitPos )
+ {
+// JP 25.04.95: Optimierung fuer SplitNode:
+// Wird am Ende vom Node gesplittet, dann verschiebe die
+// Frames vom akt. auf den neuen und erzeuge fuer den akt.
+// neue. Dadurch entfaellt das neu aufbauen vom Layout.
+
+ LockModify(); // Benachrichtigungen abschalten
+
+ // werden FlyFrames mit verschoben, so muessen diese nicht ihre
+ // Frames zerstoeren. Im SwTxtFly::SetAnchor wird es abgefragt!
+ if ( HasHints() )
+ {
+ pNode->GetOrCreateSwpHints().SetInSplitNode(true);
+ }
+
+ //Ersten Teil des Inhalts in den neuen Node uebertragen und
+ //im alten Node loeschen.
+ SwIndex aIdx( this );
+ CutText( pNode, aIdx, nSplitPos );
+
+ if( GetWrong() )
+ {
+ pNode->SetWrong( GetWrong()->SplitList( nSplitPos ) );
+ }
+ SetWrongDirty( true );
+
+ if( GetGrammarCheck() )
+ {
+ pNode->SetGrammarCheck( GetGrammarCheck()->SplitGrammarList( nSplitPos ) );
+ }
+ SetGrammarCheckDirty( true );
+
+ SetWordCountDirty( true );
+
+ // SMARTTAGS
+ if( GetSmartTags() )
+ {
+ pNode->SetSmartTags( GetSmartTags()->SplitList( nSplitPos ) );
+ }
+ SetSmartTagDirty( true );
+
+ if ( pNode->HasHints() )
+ {
+ if ( pNode->m_pSwpHints->CanBeDeleted() )
+ {
+ delete pNode->m_pSwpHints;
+ pNode->m_pSwpHints = 0;
+ }
+ else
+ {
+ pNode->m_pSwpHints->SetInSplitNode(false);
+ }
+
+ // alle zeichengebundenen Rahmen, die im neuen Absatz laden
+ // muessen aus den alten Frame entfernt werden:
+ // JP 01.10.96: alle leeren und nicht zu expandierenden
+ // Attribute loeschen
+ if ( HasHints() )
+ {
+ for ( USHORT j = m_pSwpHints->Count(); j; )
+ {
+ SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j );
+ if ( RES_TXTATR_FLYCNT == pHt ->Which() )
+ {
+ pHt->GetFlyCnt().GetFrmFmt()->DelFrms();
+ }
+ else if ( pHt->DontExpand() )
+ {
+ const xub_StrLen* const pEnd = pHt->GetEnd();
+ if (pEnd && *pHt->GetStart() == *pEnd )
+ {
+ // delete it!
+ m_pSwpHints->DeleteAtPos( j );
+ DestroyAttr( pHt );
+ }
+ }
+ }
+ }
+
+ }
+
+ SwClientIter aIter( *this );
+ SwClient* pLastFrm = aIter.GoStart();
+ if( pLastFrm )
+ {
+ do
+ { SwCntntFrm *pFrm = PTR_CAST( SwCntntFrm, pLastFrm );
+ if ( pFrm )
+ {
+ pNode->Add( pFrm );
+ if( pFrm->IsTxtFrm() && !pFrm->IsFollow() &&
+ ((SwTxtFrm*)pFrm)->GetOfst() )
+ ((SwTxtFrm*)pFrm)->SetOfst( 0 );
+ }
+ pLastFrm = aIter++;
+ } while ( pLastFrm );
+ }
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( FALSE );
+ }
+
+ UnlockModify(); // Benachrichtigungen wieder freischalten
+
+ const SwRootFrm * const pRootFrm = pNode->GetDoc()->GetRootFrm();
+ // If there is an accessible layout we must call modify even
+ // with length zero, because we have to notify about the changed
+ // text node.
+ if ( (nTxtLen != nSplitPos) ||
+ ( pRootFrm && pRootFrm->IsAnyShellAccessible() ) )
+
+ {
+ // dann sage den Frames noch, das am Ende etwas "geloescht" wurde
+ if( 1 == nTxtLen - nSplitPos )
+ {
+ SwDelChr aHint( nSplitPos );
+ pNode->SwModify::Modify( 0, &aHint );
+ }
+ else
+ {
+ SwDelTxt aHint( nSplitPos, nTxtLen - nSplitPos );
+ pNode->SwModify::Modify( 0, &aHint );
+ }
+ }
+ if ( HasHints() )
+ {
+ MoveTxtAttr_To_AttrSet();
+ }
+ pNode->MakeFrms( *this ); // neue Frames anlegen.
+ lcl_ChangeFtnRef( *this );
+ }
+ else
+ {
+ SwWrongList *pList = GetWrong();
+ SetWrong( 0, false );
+ SetWrongDirty( true );
+
+ SwGrammarMarkUp *pList3 = GetGrammarCheck();
+ SetGrammarCheck( 0, false );
+ SetGrammarCheckDirty( true );
+
+ SetWordCountDirty( true );
+
+ // SMARTTAGS
+ SwWrongList *pList2 = GetSmartTags();
+ SetSmartTags( 0, false );
+ SetSmartTagDirty( true );
+
+ SwIndex aIdx( this );
+ CutText( pNode, aIdx, nSplitPos );
+
+ // JP 01.10.96: alle leeren und nicht zu expandierenden
+ // Attribute loeschen
+ if ( HasHints() )
+ {
+ for ( USHORT j = m_pSwpHints->Count(); j; )
+ {
+ SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j );
+ const xub_StrLen* const pEnd = pHt->GetEnd();
+ if ( pHt->DontExpand() && pEnd && (*pHt->GetStart() == *pEnd) )
+ {
+ // delete it!
+ m_pSwpHints->DeleteAtPos( j );
+ DestroyAttr( pHt );
+ }
+ }
+ MoveTxtAttr_To_AttrSet();
+ }
+
+ if( pList )
+ {
+ pNode->SetWrong( pList->SplitList( nSplitPos ) );
+ SetWrong( pList, false );
+ }
+
+ if( pList3 )
+ {
+ pNode->SetGrammarCheck( pList3->SplitGrammarList( nSplitPos ) );
+ SetGrammarCheck( pList3, false );
+ }
+
+ // SMARTTAGS
+ if( pList2 )
+ {
+ pNode->SetSmartTags( pList2->SplitList( nSplitPos ) );
+ SetSmartTags( pList2, false );
+ }
+
+ if ( GetDepends() )
+ {
+ MakeFrms( *pNode ); // neue Frames anlegen.
+ }
+ lcl_ChangeFtnRef( *pNode );
+ }
+
+ {
+ //Hint fuer Pagedesc versenden. Das mueste eigntlich das Layout im
+ //Paste der Frames selbst erledigen, aber das fuehrt dann wiederum
+ //zu weiteren Folgefehlern, die mit Laufzeitkosten geloest werden
+ //muesten. #56977# #55001# #56135#
+ const SfxPoolItem *pItem;
+ if( GetDepends() && SFX_ITEM_SET == pNode->GetSwAttrSet().
+ GetItemState( RES_PAGEDESC, TRUE, &pItem ) )
+ {
+ pNode->Modify( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
+ }
+ }
+ return pNode;
+}
+
+void SwTxtNode::MoveTxtAttr_To_AttrSet()
+{
+ ASSERT( m_pSwpHints, "MoveTxtAttr_To_AttrSet without SwpHints?" );
+ for ( USHORT i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
+ {
+ SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);
+
+ if( *pHt->GetStart() )
+ break;
+
+ const xub_StrLen* pHtEndIdx = pHt->GetEnd();
+
+ if( !pHtEndIdx )
+ continue;
+
+ if ( *pHtEndIdx < m_Text.Len() || pHt->IsCharFmtAttr() )
+ break;
+
+ if( !pHt->IsDontMoveAttr() &&
+ SetAttr( pHt->GetAttr() ) )
+ {
+ m_pSwpHints->DeleteAtPos(i);
+ DestroyAttr( pHt );
+ --i;
+ }
+ }
+
+}
+
+SwCntntNode *SwTxtNode::JoinNext()
+{
+ SwNodes& rNds = GetNodes();
+ SwNodeIndex aIdx( *this );
+ if( SwCntntNode::CanJoinNext( &aIdx ) )
+ {
+ SwDoc* pDoc = rNds.GetDoc();
+ SvULongs aBkmkArr( 15, 15 );
+ _SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY );
+ SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode();
+ xub_StrLen nOldLen = m_Text.Len();
+
+ // METADATA: merge
+ this->JoinMetadatable(*pTxtNode, !this->Len(), !pTxtNode->Len());
+
+ SwWrongList *pList = GetWrong();
+ if( pList )
+ {
+ pList->JoinList( pTxtNode->GetWrong(), nOldLen );
+ SetWrongDirty( true );
+ SetWrong( 0, false );
+ }
+ else
+ {
+ pList = pTxtNode->GetWrong();
+ if( pList )
+ {
+ pList->Move( 0, nOldLen );
+ SetWrongDirty( true );
+ pTxtNode->SetWrong( 0, false );
+ }
+ }
+
+ SwGrammarMarkUp *pList3 = GetGrammarCheck();
+ if( pList3 )
+ {
+ pList3->JoinGrammarList( pTxtNode->GetGrammarCheck(), nOldLen );
+ SetGrammarCheckDirty( true );
+ SetGrammarCheck( 0, false );
+ }
+ else
+ {
+ pList3 = pTxtNode->GetGrammarCheck();
+ if( pList3 )
+ {
+ pList3->MoveGrammar( 0, nOldLen );
+ SetGrammarCheckDirty( true );
+ pTxtNode->SetGrammarCheck( 0, false );
+ }
+ }
+
+ // SMARTTAGS
+ SwWrongList *pList2 = GetSmartTags();
+ if( pList2 )
+ {
+ pList2->JoinList( pTxtNode->GetSmartTags(), nOldLen );
+ SetSmartTagDirty( true );
+ SetSmartTags( 0, false );
+ }
+ else
+ {
+ pList2 = pTxtNode->GetSmartTags();
+ if( pList2 )
+ {
+ pList2->Move( 0, nOldLen );
+ SetSmartTagDirty( true );
+ pTxtNode->SetSmartTags( 0, false );
+ }
+ }
+
+ { // wg. SwIndex
+ pTxtNode->CutText( this, SwIndex(pTxtNode), pTxtNode->Len() );
+ }
+ // verschiebe noch alle Bookmarks/TOXMarks
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( pDoc, aBkmkArr, GetIndex(), nOldLen );
+
+ if( pTxtNode->HasAnyIndex() )
+ {
+ // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
+ pDoc->CorrAbs( aIdx, SwPosition( *this ), nOldLen, TRUE );
+ }
+ rNds.Delete(aIdx);
+ SetWrong( pList, false );
+ SetGrammarCheck( pList3, false );
+ SetSmartTags( pList2, false ); // SMARTTAGS
+ InvalidateNumRule();
+ }
+ else {
+ ASSERT( FALSE, "kein TxtNode." );
+ }
+
+ return this;
+}
+
+SwCntntNode *SwTxtNode::JoinPrev()
+{
+ SwNodes& rNds = GetNodes();
+ SwNodeIndex aIdx( *this );
+ if( SwCntntNode::CanJoinPrev( &aIdx ) )
+ {
+ SwDoc* pDoc = rNds.GetDoc();
+ SvULongs aBkmkArr( 15, 15 );
+ _SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY );
+ SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode();
+ xub_StrLen nLen = pTxtNode->Len();
+
+ SwWrongList *pList = pTxtNode->GetWrong();
+ if( pList )
+ {
+ pList->JoinList( GetWrong(), Len() );
+ SetWrongDirty( true );
+ pTxtNode->SetWrong( 0, false );
+ SetWrong( NULL );
+ }
+ else
+ {
+ pList = GetWrong();
+ if( pList )
+ {
+ pList->Move( 0, nLen );
+ SetWrongDirty( true );
+ SetWrong( 0, false );
+ }
+ }
+
+ SwGrammarMarkUp *pList3 = pTxtNode->GetGrammarCheck();
+ if( pList3 )
+ {
+ pList3->JoinGrammarList( GetGrammarCheck(), Len() );
+ SetGrammarCheckDirty( true );
+ pTxtNode->SetGrammarCheck( 0, false );
+ SetGrammarCheck( NULL );
+ }
+ else
+ {
+ pList3 = GetGrammarCheck();
+ if( pList3 )
+ {
+ pList3->MoveGrammar( 0, nLen );
+ SetGrammarCheckDirty( true );
+ SetGrammarCheck( 0, false );
+ }
+ }
+
+ // SMARTTAGS
+ SwWrongList *pList2 = pTxtNode->GetSmartTags();
+ if( pList2 )
+ {
+ pList2->JoinList( GetSmartTags(), Len() );
+ SetSmartTagDirty( true );
+ pTxtNode->SetSmartTags( 0, false );
+ SetSmartTags( NULL );
+ }
+ else
+ {
+ pList2 = GetSmartTags();
+ if( pList2 )
+ {
+ pList2->Move( 0, nLen );
+ SetSmartTagDirty( true );
+ SetSmartTags( 0, false );
+ }
+ }
+
+ { // wg. SwIndex
+ pTxtNode->CutText( this, SwIndex(this), SwIndex(pTxtNode), nLen );
+ }
+ // verschiebe noch alle Bookmarks/TOXMarks
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( pDoc, aBkmkArr, GetIndex() );
+
+ if( pTxtNode->HasAnyIndex() )
+ {
+ // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
+ pDoc->CorrAbs( aIdx, SwPosition( *this ), nLen, TRUE );
+ }
+ rNds.Delete(aIdx);
+ SetWrong( pList, false );
+ SetGrammarCheck( pList3, false );
+ SetSmartTags( pList2, false );
+ InvalidateNumRule();
+ }
+ else {
+ ASSERT( FALSE, "kein TxtNode." );
+ }
+
+ return this;
+}
+
+// erzeugt einen AttrSet mit Bereichen fuer Frame-/Para/Char-Attributen
+void SwTxtNode::NewAttrSet( SwAttrPool& rPool )
+{
+ ASSERT( !mpAttrSet.get(), "AttrSet ist doch gesetzt" );
+ SwAttrSet aNewAttrSet( rPool, aTxtNodeSetRange );
+
+ // put names of parent style and conditional style:
+ const SwFmtColl* pAnyFmtColl = &GetAnyFmtColl();
+ const SwFmtColl* pFmtColl = GetFmtColl();
+ String sVal;
+ SwStyleNameMapper::FillProgName( pAnyFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ SfxStringItem aAnyFmtColl( RES_FRMATR_STYLE_NAME, sVal );
+ if ( pFmtColl != pAnyFmtColl )
+ SwStyleNameMapper::FillProgName( pFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ SfxStringItem aFmtColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal );
+ aNewAttrSet.Put( aAnyFmtColl );
+ aNewAttrSet.Put( aFmtColl );
+
+ aNewAttrSet.SetParent( &pAnyFmtColl->GetAttrSet() );
+ mpAttrSet = GetDoc()->GetIStyleAccess().getAutomaticStyle( aNewAttrSet, IStyleAccess::AUTO_STYLE_PARA );
+}
+
+
+// override SwIndexReg::Update => text hints do not need SwIndex for start/end!
+void SwTxtNode::Update( SwIndex const & rPos, const xub_StrLen nChangeLen,
+ const bool bNegative, const bool bDelete )
+{
+ SetAutoCompleteWordDirty( TRUE );
+
+ ::std::auto_ptr<TmpHints> pCollector;
+ const xub_StrLen nChangePos = rPos.GetIndex();
+
+ if ( HasHints() )
+ {
+ if ( bNegative )
+ {
+ const xub_StrLen nChangeEnd = nChangePos + nChangeLen;
+ for ( USHORT n = 0; n < m_pSwpHints->Count(); ++n )
+ {
+ SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n);
+ xub_StrLen * const pStart = pHint->GetStart();
+ if ( *pStart > nChangePos )
+ {
+ if ( *pStart > nChangeEnd )
+ {
+ *pStart = *pStart - nChangeLen;
+ }
+ else
+ {
+ *pStart = nChangePos;
+ }
+ }
+
+ xub_StrLen * const pEnd = pHint->GetEnd();
+ if (pEnd)
+ {
+ if ( *pEnd > nChangePos )
+ {
+ if( *pEnd > nChangeEnd )
+ {
+ *pEnd = *pEnd - nChangeLen;
+ }
+ else
+ {
+ *pEnd = nChangePos;
+ }
+ }
+ }
+ }
+
+ m_pSwpHints->MergePortions( *this );
+ }
+ else
+ {
+ bool bNoExp = false;
+ bool bResort = false;
+ const USHORT coArrSz = static_cast<USHORT>(RES_TXTATR_WITHEND_END) -
+ static_cast<USHORT>(RES_CHRATR_BEGIN);
+
+ BOOL aDontExp[ coArrSz ];
+ memset( &aDontExp, 0, coArrSz * sizeof(BOOL) );
+
+ for ( USHORT n = 0; n < m_pSwpHints->Count(); ++n )
+ {
+ SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n);
+ xub_StrLen * const pStart = pHint->GetStart();
+ xub_StrLen * const pEnd = pHint->GetEnd();
+ if ( *pStart >= nChangePos )
+ {
+ *pStart = *pStart + nChangeLen;
+ if ( pEnd )
+ {
+ *pEnd = *pEnd + nChangeLen;
+ }
+ }
+ else if ( pEnd && (*pEnd >= nChangePos) )
+ {
+ if ( (*pEnd > nChangePos) || IsIgnoreDontExpand() )
+ {
+ *pEnd = *pEnd + nChangeLen;
+ }
+ else // *pEnd == nChangePos
+ {
+ USHORT nWhPos;
+ const USHORT nWhich = pHint->Which();
+
+ ASSERT(!isCHRATR(nWhich), "Update: char attr hint?");
+ if (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich))
+ {
+ nWhPos = static_cast<USHORT>(nWhich -
+ RES_CHRATR_BEGIN);
+ }
+ else
+ continue;
+
+ if( aDontExp[ nWhPos ] )
+ continue;
+
+ if ( pHint->DontExpand() )
+ {
+ pHint->SetDontExpand( false );
+ bResort = true;
+ if ( pHint->IsCharFmtAttr() )
+ {
+ bNoExp = true;
+ aDontExp[ static_cast<USHORT>(RES_TXTATR_CHARFMT) - static_cast<USHORT>(RES_CHRATR_BEGIN) ]
+ = TRUE;
+ aDontExp[ static_cast<USHORT>(RES_TXTATR_INETFMT) - static_cast<USHORT>(RES_CHRATR_BEGIN) ]
+ = TRUE;
+ }
+ else
+ aDontExp[ nWhPos ] = TRUE;
+ }
+ else if( bNoExp )
+ {
+ if ( !pCollector.get() )
+ {
+ pCollector.reset( new TmpHints );
+ }
+ USHORT nCollCnt = pCollector->Count();
+ for( USHORT i = 0; i < nCollCnt; ++i )
+ {
+ SwTxtAttr *pTmp = (*pCollector)[ i ];
+ if( nWhich == pTmp->Which() )
+ {
+ pCollector->Remove( i );
+ SwTxtAttr::Destroy( pTmp,
+ GetDoc()->GetAttrPool() );
+ break;
+ }
+ }
+ SwTxtAttr * const pTmp = MakeTxtAttr( *GetDoc(),
+ pHint->GetAttr(),
+ nChangePos, nChangePos + nChangeLen);
+ pCollector->C40_INSERT( SwTxtAttr, pTmp, pCollector->Count() );
+ }
+ else
+ {
+ *pEnd = *pEnd + nChangeLen;
+ }
+ }
+ }
+ }
+ if ( bResort )
+ {
+ m_pSwpHints->Resort();
+ }
+ }
+ }
+
+ SwIndexReg aTmpIdxReg;
+ if ( !bNegative && !bDelete )
+ {
+ const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();
+ for ( USHORT i = 0; i < rTbl.Count(); ++i )
+ {
+ SwRedline *const pRedl = rTbl[ i ];
+ if ( pRedl->HasMark() )
+ {
+ SwPosition* const pEnd = pRedl->End();
+ if ( this == &pEnd->nNode.GetNode() &&
+ *pRedl->GetPoint() != *pRedl->GetMark() )
+ {
+ SwIndex & rIdx = pEnd->nContent;
+ if (nChangePos == rIdx.GetIndex())
+ {
+ rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
+ }
+ }
+ }
+ else if ( this == &pRedl->GetPoint()->nNode.GetNode() )
+ {
+ SwIndex & rIdx = pRedl->GetPoint()->nContent;
+ if (nChangePos == rIdx.GetIndex())
+ {
+ rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
+ // mst: FIXME: why does this adjust the unused position???
+ SwIndex * pIdx;
+ if ( &pRedl->GetBound( true ) == pRedl->GetPoint() )
+ {
+ pRedl->GetBound( false ) = pRedl->GetBound( true );
+ pIdx = &pRedl->GetBound( false ).nContent;
+ }
+ else
+ {
+ pRedl->GetBound( true ) = pRedl->GetBound( false );
+ pIdx = &pRedl->GetBound( true ).nContent;
+ }
+ pIdx->Assign( &aTmpIdxReg, pIdx->GetIndex() );
+ }
+ }
+ }
+
+ const IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess();
+ for(IDocumentMarkAccess::const_iterator_t ppMark =
+ pMarkAccess->getMarksBegin();
+ ppMark != pMarkAccess->getMarksEnd();
+ ppMark++)
+ {
+ // Bookmarks must never grow to either side, when
+ // editing (directly) to the left or right (#i29942#)!
+ // And a bookmark with same start and end must remain
+ // to the left of the inserted text (used in XML import).
+ const ::sw::mark::IMark* const pMark = ppMark->get();
+ const SwPosition* pEnd = &pMark->GetMarkEnd();
+ SwIndex & rIdx = const_cast<SwIndex&>(pEnd->nContent);
+ if( this == &pEnd->nNode.GetNode() &&
+ rPos.GetIndex() == rIdx.GetIndex() )
+ {
+ rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
+ }
+ }
+ }
+
+ // base class
+ SwIndexReg::Update( rPos, nChangeLen, bNegative, bDelete );
+
+ if ( pCollector.get() )
+ {
+ const USHORT nCount = pCollector->Count();
+ for ( USHORT i = 0; i < nCount; ++i )
+ {
+ m_pSwpHints->TryInsertHint( (*pCollector)[ i ], *this );
+ }
+ }
+
+ aTmpIdxReg.MoveTo( *this );
+}
+
+void SwTxtNode::_ChgTxtCollUpdateNum( const SwTxtFmtColl *pOldColl,
+ const SwTxtFmtColl *pNewColl)
+{
+ SwDoc* pDoc = GetDoc();
+ ASSERT( pDoc, "Kein Doc?" );
+ // erfrage die OutlineLevel und update gegebenenfalls das Nodes-Array,
+ // falls sich die Level geaendert haben !
+ //const BYTE nOldLevel = pOldColl ? pOldColl->GetOutlineLevel():NO_NUMBERING;//#outline level,removed by zhaojianwei
+ //const BYTE nNewLevel = pNewColl ? pNewColl->GetOutlineLevel():NO_NUMBERING;//<-end,zhaojianwei
+ const int nOldLevel = pOldColl && pOldColl->IsAssignedToListLevelOfOutlineStyle() ?
+ pOldColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
+ const int nNewLevel = pNewColl && pNewColl->IsAssignedToListLevelOfOutlineStyle() ?
+ pNewColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
+
+// if ( NO_NUMBERING != nNewLevel ) //#outline level,zhaojianwei
+ if ( MAXLEVEL != nNewLevel ) //<-end,zhaojianwei
+ {
+ SetAttrListLevel(nNewLevel);
+ }
+
+ {
+ if (pDoc)
+ pDoc->GetNodes().UpdateOutlineNode(*this);
+ }
+
+
+ SwNodes& rNds = GetNodes();
+ // Update beim Level 0 noch die Fussnoten !!
+ if( ( !nNewLevel || !nOldLevel) && pDoc->GetFtnIdxs().Count() &&
+ FTNNUM_CHAPTER == pDoc->GetFtnInfo().eNum &&
+ rNds.IsDocNodes() )
+ {
+ SwNodeIndex aTmpIndex( rNds, GetIndex());
+
+ pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex);
+ }
+
+//FEATURE::CONDCOLL
+ if( /*pOldColl != pNewColl && pNewColl && */
+ RES_CONDTXTFMTCOLL == pNewColl->Which() )
+ {
+ // Erfrage die akt. Condition des TextNodes:
+ ChkCondColl();
+ }
+//FEATURE::CONDCOLL
+}
+
+// Wenn man sich genau am Ende einer Text- bzw. INetvorlage befindet,
+// bekommt diese das DontExpand-Flag verpasst
+
+BOOL SwTxtNode::DontExpandFmt( const SwIndex& rIdx, bool bFlag,
+ BOOL bFmtToTxtAttributes )
+{
+ const xub_StrLen nIdx = rIdx.GetIndex();
+ if ( bFmtToTxtAttributes && nIdx == m_Text.Len() )
+ {
+ FmtToTxtAttr( this );
+ }
+
+ BOOL bRet = FALSE;
+ if ( HasHints() )
+ {
+ const USHORT nEndCnt = m_pSwpHints->GetEndCount();
+ USHORT nPos = nEndCnt;
+ while( nPos )
+ {
+ SwTxtAttr *pTmp = m_pSwpHints->GetEnd( --nPos );
+ xub_StrLen *pEnd = pTmp->GetEnd();
+ if( !pEnd || *pEnd > nIdx )
+ continue;
+ if( nIdx != *pEnd )
+ nPos = 0;
+ else if( bFlag != pTmp->DontExpand() && !pTmp->IsLockExpandFlag()
+ && *pEnd > *pTmp->GetStart())
+ {
+ bRet = TRUE;
+ m_pSwpHints->NoteInHistory( pTmp );
+ pTmp->SetDontExpand( bFlag );
+ }
+ }
+ }
+ return bRet;
+}
+
+
+// gebe das vorgegebene Attribut, welches an der TextPosition (rIdx)
+// gesetzt ist, zurueck. Gibt es keines, returne 0-Pointer.
+// (gesetzt heisst, je nach bExpand ?
+// Start < rIdx <= End
+// : Start <= rIdx < End )
+
+SwTxtAttr* SwTxtNode::GetTxtAttr( const SwIndex& rIdx, USHORT nWhichHt,
+ BOOL bExpand ) const
+{
+ const SwTxtAttr* pRet = 0;
+ const SwTxtAttr* pHt = 0;
+ const xub_StrLen *pEndIdx = 0;
+ const xub_StrLen nIdx = rIdx.GetIndex();
+ const USHORT nSize = m_pSwpHints ? m_pSwpHints->Count() : 0;
+
+ for( USHORT i = 0; i < nSize; ++i )
+ {
+ // ist der Attribut-Anfang schon groesser als der Idx ?
+ pHt = (*m_pSwpHints)[i];
+ if ( nIdx < *(pHt->GetStart()) )
+ break; // beenden, kein gueltiges Attribut
+
+ // ist es das gewuenschte Attribut ?
+ if( pHt->Which() != nWhichHt )
+ continue; // nein, weiter
+
+ pEndIdx = pHt->GetEnd();
+ // liegt innerhalb des Bereiches ??
+ if( !pEndIdx )
+ {
+ if( *pHt->GetStart() == nIdx )
+ {
+ pRet = pHt;
+ break;
+ }
+ }
+ else if( *pHt->GetStart() <= nIdx && nIdx <= *pEndIdx )
+ {
+ // Wenn bExpand gesetzt ist, wird das Verhalten bei Eingabe
+ // simuliert, d.h. der Start wuede verschoben, das Ende expandiert,
+ if( bExpand )
+ {
+ if( *pHt->GetStart() < nIdx )
+ pRet = pHt;
+ }
+ else
+ {
+ if( nIdx < *pEndIdx )
+ pRet = pHt; // den am dichtesten liegenden
+ }
+ }
+ }
+ return (SwTxtAttr*)pRet; // kein gueltiges Attribut gefunden !!
+}
+
+/*************************************************************************
+ * CopyHint()
+ *************************************************************************/
+
+SwCharFmt* lcl_FindCharFmt( const SwCharFmts* pCharFmts, const XubString& rName )
+{
+ if( rName.Len() )
+ {
+ SwCharFmt* pFmt;
+ USHORT nArrLen = pCharFmts->Count();
+ for( USHORT i = 1; i < nArrLen; i++ )
+ {
+ pFmt = (*pCharFmts)[ i ];
+ if( pFmt->GetName().CompareTo( rName ) == COMPARE_EQUAL )
+ return pFmt;
+ }
+ }
+ return NULL;
+}
+
+void lcl_CopyHint( const USHORT nWhich, const SwTxtAttr * const pHt,
+ SwTxtAttr *const pNewHt, SwDoc *const pOtherDoc, SwTxtNode *const pDest )
+{
+ ASSERT( nWhich == pHt->Which(), "Falsche Hint-Id" );
+ switch( nWhich )
+ {
+ // Wenn wir es mit einem Fussnoten-Attribut zu tun haben,
+ // muessen wir natuerlich auch den Fussnotenbereich kopieren.
+ case RES_TXTATR_FTN :
+ static_cast<const SwTxtFtn*>(pHt)->CopyFtn(
+ static_cast<SwTxtFtn*>(pNewHt));
+ break;
+
+ // Beim Kopieren von Feldern in andere Dokumente
+ // muessen die Felder bei ihren neuen Feldtypen angemeldet werden.
+
+ // TabellenFormel muessen relativ kopiert werden.
+ case RES_TXTATR_FIELD :
+ {
+ const SwFmtFld& rFld = pHt->GetFld();
+ if( pOtherDoc )
+ {
+ static_cast<const SwTxtFld*>(pHt)->CopyFld(
+ static_cast<SwTxtFld*>(pNewHt) );
+ }
+
+ // Tabellenformel ??
+ if( RES_TABLEFLD == rFld.GetFld()->GetTyp()->Which()
+ && static_cast<const SwTblField*>(rFld.GetFld())->IsIntrnlName())
+ {
+ // wandel die interne in eine externe Formel um
+ const SwTableNode* const pDstTblNd =
+ static_cast<const SwTxtFld*>(pHt)->
+ GetTxtNode().FindTableNode();
+ if( pDstTblNd )
+ {
+ SwTblField* const pTblFld = const_cast<SwTblField*>(
+ static_cast<const SwTblField*>(
+ pNewHt->GetFld().GetFld()));
+ pTblFld->PtrToBoxNm( &pDstTblNd->GetTable() );
+ }
+ }
+ }
+ break;
+
+ case RES_TXTATR_TOXMARK :
+ if( pOtherDoc && pDest && pDest->GetpSwpHints()
+ && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
+ {
+ // Beim Kopieren von TOXMarks(Client) in andere Dokumente
+ // muss der Verzeichnis (Modify) ausgetauscht werden
+ static_cast<SwTxtTOXMark*>(pNewHt)->CopyTOXMark( pOtherDoc );
+ }
+ break;
+
+ case RES_TXTATR_CHARFMT :
+ // Wenn wir es mit einer Zeichenvorlage zu tun haben,
+ // muessen wir natuerlich auch die Formate kopieren.
+ if( pDest && pDest->GetpSwpHints()
+ && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
+ {
+ SwCharFmt* pFmt =
+ static_cast<SwCharFmt*>(pHt->GetCharFmt().GetCharFmt());
+
+ if( pFmt && pOtherDoc )
+ {
+ pFmt = pOtherDoc->CopyCharFmt( *pFmt );
+ }
+ const_cast<SwFmtCharFmt&>( static_cast<const SwFmtCharFmt&>(
+ pNewHt->GetCharFmt() ) ).SetCharFmt( pFmt );
+ }
+ break;
+ case RES_TXTATR_INETFMT :
+ {
+ // Wenn wir es mit benutzerdefinierten INet-Zeichenvorlagen
+ // zu tun haben, muessen wir natuerlich auch die Formate kopieren.
+ if( pOtherDoc && pDest && pDest->GetpSwpHints()
+ && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
+ {
+ const SwDoc* const pDoc = static_cast<const SwTxtINetFmt*>(pHt)
+ ->GetTxtNode().GetDoc();
+ if ( pDoc )
+ {
+ const SwCharFmts* pCharFmts = pDoc->GetCharFmts();
+ const SwFmtINetFmt& rFmt = pHt->GetINetFmt();
+ SwCharFmt* pFmt;
+ pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetINetFmt() );
+ if( pFmt )
+ pOtherDoc->CopyCharFmt( *pFmt );
+ pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetVisitedFmt() );
+ if( pFmt )
+ pOtherDoc->CopyCharFmt( *pFmt );
+ }
+ }
+ //JP 24.04.98: Bug 49753 - ein TextNode muss am Attribut
+ // gesetzt sein, damit die Vorlagen erzeugt
+ // werden koenne
+ SwTxtINetFmt* const pINetHt = static_cast<SwTxtINetFmt*>(pNewHt);
+ if ( !pINetHt->GetpTxtNode() )
+ {
+ pINetHt->ChgTxtNode( pDest );
+ }
+
+ //JP 22.10.97: Bug 44875 - Verbindung zum Format herstellen
+ pINetHt->GetCharFmt();
+ break;
+ }
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ ASSERT(pNewHt, "copying META should not fail! cannot call DoCopy");
+ ASSERT(pDest && (CH_TXTATR_INWORD ==
+ pDest->GetTxt().GetChar(*pNewHt->GetStart())),
+ "missing CH_TXTATR?");
+ if (pNewHt)
+ {
+ SwFmtMeta & rMeta(static_cast<SwFmtMeta&>(pNewHt->GetAttr()));
+ rMeta.DoCopy( const_cast<SwFmtMeta&>(pHt->GetMeta()) );
+ }
+ break;
+ }
+}
+
+/*************************************************************************
+|* SwTxtNode::CopyAttr()
+|* Beschreibung kopiert Attribute an der Position nStart in pDest.
+|* BP 7.6.93: Es werden mit Absicht nur die Attribute _mit_ EndIdx
+|* kopiert! CopyAttr wird vornehmlich dann gerufen,
+|* wenn Attribute fuer einen Node mit leerem String
+|* gesetzt werden sollen.
+*************************************************************************/
+
+void SwTxtNode::CopyAttr( SwTxtNode *pDest, const xub_StrLen nTxtStartIdx,
+ const xub_StrLen nOldPos )
+{
+ if ( HasHints() ) // keine Attribute, keine Kekse
+ {
+ SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ?
+ pDest->GetDoc() : 0;
+
+ for ( USHORT i = 0; i < m_pSwpHints->Count(); i++ )
+ {
+ SwTxtAttr *const pHt = m_pSwpHints->GetTextHint(i);
+ xub_StrLen const nAttrStartIdx = *pHt->GetStart();
+ if ( nTxtStartIdx < nAttrStartIdx )
+ break; // ueber das Textende, da nLen == 0
+
+ const xub_StrLen *const pEndIdx = pHt->GetEnd();
+ if ( pEndIdx && !pHt->HasDummyChar() )
+ {
+ if( ( *pEndIdx > nTxtStartIdx ||
+ ( *pEndIdx == nTxtStartIdx &&
+ nAttrStartIdx == nTxtStartIdx ) ) )
+ {
+ USHORT const nWhich = pHt->Which();
+ if ( RES_TXTATR_REFMARK != nWhich )
+ {
+ // attribute in the area => copy
+ SwTxtAttr *const pNewHt = pDest->InsertItem(
+ pHt->GetAttr(), nOldPos, nOldPos );
+ if ( pNewHt )
+ {
+ lcl_CopyHint( nWhich, pHt, pNewHt,
+ pOtherDoc, pDest );
+ }
+ }
+ else if( !pOtherDoc ? GetDoc()->IsCopyIsMove()
+ : 0 == pOtherDoc->GetRefMark(
+ pHt->GetRefMark().GetRefName() ) )
+ {
+ pDest->InsertItem( pHt->GetAttr(), nOldPos, nOldPos );
+ }
+ }
+ }
+ }
+ }
+
+ if( this != pDest )
+ {
+ // Frames benachrichtigen, sonst verschwinden die Ftn-Nummern
+ SwUpdateAttr aHint( nOldPos, nOldPos, 0 );
+ pDest->Modify( 0, &aHint );
+ }
+}
+
+/*************************************************************************
+|* SwTxtNode::Copy()
+|* Beschreibung kopiert Zeichen und Attibute in pDest,
+|* wird angehaengt
+*************************************************************************/
+
+// --> OD 2008-11-18 #i96213#
+// introduction of new optional parameter to control, if all attributes have to be copied.
+void SwTxtNode::CopyText( SwTxtNode *const pDest,
+ const SwIndex &rStart,
+ const xub_StrLen nLen,
+ const bool bForceCopyOfAllAttrs )
+{
+ SwIndex aIdx( pDest, pDest->m_Text.Len() );
+ CopyText( pDest, aIdx, rStart, nLen, bForceCopyOfAllAttrs );
+}
+// <--
+
+// --> OD 2008-11-18 #i96213#
+// introduction of new optional parameter to control, if all attributes have to be copied.
+void SwTxtNode::CopyText( SwTxtNode *const pDest,
+ const SwIndex &rDestStart,
+ const SwIndex &rStart,
+ xub_StrLen nLen,
+ const bool bForceCopyOfAllAttrs )
+// <--
+{
+ xub_StrLen nTxtStartIdx = rStart.GetIndex();
+ xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken
+
+ if( !nLen )
+ {
+ // wurde keine Laenge angegeben, dann Kopiere die Attribute
+ // an der Position rStart.
+ CopyAttr( pDest, nTxtStartIdx, nDestStart );
+
+ // harte Absatz umspannende Attribute kopieren
+ if( HasSwAttrSet() )
+ {
+ // alle, oder nur die CharAttribute ?
+ // --> OD 2008-11-18 #i96213#
+ if ( !bForceCopyOfAllAttrs &&
+ ( nDestStart ||
+ pDest->HasSwAttrSet() ||
+ nLen != pDest->GetTxt().Len() ) )
+ // <--
+ {
+ SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+ aCharSet.Put( *GetpSwAttrSet() );
+ if( aCharSet.Count() )
+ {
+ pDest->SetAttr( aCharSet, nDestStart, nDestStart );
+ }
+ }
+ else
+ {
+ GetpSwAttrSet()->CopyToModify( *pDest );
+ }
+ }
+ return;
+ }
+
+ // 1. Text kopieren
+ const xub_StrLen oldLen = pDest->m_Text.Len();
+ //JP 15.02.96: Bug 25537 - Attributbehandlung am Ende fehlt! Darum
+ // ueber die InsertMethode den Text einfuegen und nicht
+ // selbst direkt
+ pDest->InsertText( m_Text.Copy( nTxtStartIdx, nLen ), rDestStart,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+
+ // um reale Groesse Updaten !
+ nLen = pDest->m_Text.Len() - oldLen;
+ if ( !nLen ) // string not longer?
+ return;
+
+ SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ?
+ pDest->GetDoc() : 0;
+
+ // harte Absatz umspannende Attribute kopieren
+ if( HasSwAttrSet() )
+ {
+ // alle, oder nur die CharAttribute ?
+ // --> OD 2008-11-18 #i96213#
+ if ( !bForceCopyOfAllAttrs &&
+ ( nDestStart ||
+ pDest->HasSwAttrSet() ||
+ nLen != pDest->GetTxt().Len() ) )
+ // <--
+ {
+ SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+ aCharSet.Put( *GetpSwAttrSet() );
+ if( aCharSet.Count() )
+ {
+ pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
+ }
+ }
+ else
+ {
+ GetpSwAttrSet()->CopyToModify( *pDest );
+ }
+ }
+
+ const bool bUndoNodes = !pOtherDoc && GetDoc()->GetUndoNds() == &GetNodes();
+
+ // Ende erst jetzt holen, weil beim Kopieren in sich selbst der
+ // Start-Index und alle Attribute vorher aktualisiert werden.
+ nTxtStartIdx = rStart.GetIndex();
+ const xub_StrLen nEnd = nTxtStartIdx + nLen;
+
+ // 2. Attribute kopieren
+ // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
+ // des Attributs hinter dem zu kopierenden Bereich liegt
+ const USHORT nSize = m_pSwpHints ? m_pSwpHints->Count() : 0;
+
+ // wird in sich selbst kopiert, dann kann beim Einfuegen ein
+ // Attribut geloescht werden. Darum erst ins Tmp-Array kopieren und
+ // dann erst ins eigene uebertragen.
+ SwpHts aArr( 5 );
+
+ // Del-Array fuer alle RefMarks ohne Ausdehnung
+ SwpHts aRefMrkArr;
+
+ //Achtung: kann ungueltig sein!!
+ for (USHORT n = 0; ( n < nSize ); ++n)
+ {
+ const xub_StrLen nAttrStartIdx = *(*m_pSwpHints)[n]->GetStart();
+ if (!( nAttrStartIdx < nEnd))
+ break;
+
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n);
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ const USHORT nWhich = pHt->Which();
+
+ // JP 26.04.94: REFMARK's werden nie kopiert. Hat das Refmark aber
+ // keinen Bereich umspannt, so steht im Text ein 255
+ // dieses muss entfernt werden. Trick: erst kopieren,
+ // erkennen und sammeln, nach dem kopieren Loeschen.
+ // Nimmt sein Zeichen mit ins Grab !!
+ // JP 14.08.95: Duerfen RefMarks gemovt werden?
+ int bCopyRefMark = RES_TXTATR_REFMARK == nWhich && ( bUndoNodes ||
+ (!pOtherDoc ? GetDoc()->IsCopyIsMove()
+ : 0 == pOtherDoc->GetRefMark(
+ pHt->GetRefMark().GetRefName() )));
+
+ if( pEndIdx && RES_TXTATR_REFMARK == nWhich && !bCopyRefMark )
+ {
+ continue;
+ }
+
+ xub_StrLen nAttrStt;
+ xub_StrLen nAttrEnd;
+
+ if( nAttrStartIdx < nTxtStartIdx )
+ {
+ // start is before selection
+ // copy hints with end and CH_TXTATR only if dummy char is copied
+ if ( pEndIdx && (*pEndIdx > nTxtStartIdx) && !pHt->HasDummyChar() )
+ {
+ // attribute with extent and the end is in the selection
+ nAttrStt = nDestStart;
+ nAttrEnd = (*pEndIdx > nEnd)
+ ? rDestStart.GetIndex()
+ : nDestStart + (*pEndIdx) - nTxtStartIdx;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else
+ {
+ // start is in the selection
+ nAttrStt = nDestStart + ( nAttrStartIdx - nTxtStartIdx );
+ if( pEndIdx )
+ {
+ nAttrEnd = *pEndIdx > nEnd
+ ? rDestStart.GetIndex()
+ : nDestStart + ( *pEndIdx - nTxtStartIdx );
+ }
+ else
+ {
+ nAttrEnd = nAttrStt;
+ }
+ }
+
+ SwTxtAttr * pNewHt = 0;
+
+ if( pDest == this )
+ {
+ // die Daten kopieren
+ pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
+ nAttrStt, nAttrEnd );
+
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//JP 23.04.95: erstmal so gesondert hier behandeln. Am Besten ist es
+// aber im CopyFtn wenn die pDestFtn keinen StartNode hat,
+// sich diesen dann anlegt.
+// Aber so kurz vor der BETA besser nicht anfassen.
+ if( RES_TXTATR_FTN == nWhich )
+ {
+ SwTxtFtn* pFtn = (SwTxtFtn*)pNewHt;
+ pFtn->ChgTxtNode( this );
+ pFtn->MakeNewTextSection( GetNodes() );
+ lcl_CopyHint( nWhich, pHt, pFtn, 0, 0 );
+ pFtn->ChgTxtNode( 0 );
+ }
+ else
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ {
+ lcl_CopyHint( nWhich, pHt, pNewHt, 0, pDest );
+ }
+ aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() );
+ }
+ else
+ {
+ pNewHt = pDest->InsertItem( pHt->GetAttr(), nAttrStt,
+ nAttrEnd, nsSetAttrMode::SETATTR_NOTXTATRCHR );
+ lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
+ }
+
+ if( RES_TXTATR_REFMARK == nWhich && !pEndIdx && !bCopyRefMark )
+ {
+ aRefMrkArr.C40_INSERT( SwTxtAttr, pNewHt, aRefMrkArr.Count() );
+ }
+ }
+
+ // nur falls im Array Attribute stehen (kann nur beim Kopieren
+ // sich selbst passieren!!)
+ for ( USHORT i = 0; i < aArr.Count(); ++i )
+ {
+ InsertHint( aArr[ i ], nsSetAttrMode::SETATTR_NOTXTATRCHR );
+ }
+
+ if( pDest->GetpSwpHints() )
+ {
+ for ( USHORT i = 0; i < aRefMrkArr.Count(); ++i )
+ {
+ SwTxtAttr * const pNewHt = aRefMrkArr[i];
+ if( pNewHt->GetEnd() )
+ {
+ pDest->GetpSwpHints()->Delete( pNewHt );
+ pDest->DestroyAttr( pNewHt );
+ }
+ else
+ {
+ const SwIndex aIdx( pDest, *pNewHt->GetStart() );
+ pDest->EraseText( aIdx, 1 );
+ }
+ }
+ }
+
+ CHECK_SWPHINTS(this);
+}
+
+
+void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
+ const IDocumentContentOperations::InsertFlags nMode )
+{
+ ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::InsertText: invalid index." );
+ ASSERT( (ULONG)m_Text.Len() + (ULONG)rStr.Len() <= STRING_LEN,
+ "SwTxtNode::InsertText: node text with insertion > STRING_LEN." );
+
+ xub_StrLen aPos = rIdx.GetIndex();
+ xub_StrLen nLen = m_Text.Len() - aPos;
+ m_Text.Insert( rStr, aPos );
+ nLen = m_Text.Len() - aPos - nLen;
+
+ if ( !nLen ) return;
+
+ BOOL bOldExpFlg = IsIgnoreDontExpand();
+ if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
+ {
+ SetIgnoreDontExpand( TRUE );
+ }
+
+ Update( rIdx, nLen ); // text content changed!
+
+ if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
+ {
+ SetIgnoreDontExpand( bOldExpFlg );
+ }
+
+ // analog zu Insert(char) in txtedt.cxx:
+ // 1) bei bHintExp leere Hints an rIdx.GetIndex suchen und aufspannen
+ // 2) bei bHintExp == FALSE mitgezogene Feldattribute zuruecksetzen
+
+ if ( HasHints() )
+ {
+ for ( USHORT i = 0; i < m_pSwpHints->Count() &&
+ rIdx >= *(*m_pSwpHints)[i]->GetStart(); ++i )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint( i );
+ xub_StrLen * const pEndIdx = pHt->GetEnd();
+ if( !pEndIdx )
+ continue;
+
+ if( rIdx == *pEndIdx )
+ {
+ if ( (nMode & IDocumentContentOperations::INS_NOHINTEXPAND) ||
+ (!(nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
+ && pHt->DontExpand()) )
+ {
+ // bei leeren Attributen auch Start veraendern
+ if( rIdx == *pHt->GetStart() )
+ *pHt->GetStart() = *pHt->GetStart() - nLen;
+ *pEndIdx = *pEndIdx - nLen;
+ m_pSwpHints->DeleteAtPos(i);
+ InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+ // empty hints at insert position?
+ else if ( (nMode & IDocumentContentOperations::INS_EMPTYEXPAND)
+ && (*pEndIdx == *pHt->GetStart()) )
+ {
+ *pHt->GetStart() = *pHt->GetStart() - nLen;
+ const USHORT nAktLen = m_pSwpHints->Count();
+ m_pSwpHints->DeleteAtPos(i);
+ InsertHint( pHt/* AUTOSTYLES:, nsSetAttrMode::SETATTR_NOHINTADJUST*/ );
+ if ( nAktLen > m_pSwpHints->Count() && i )
+ {
+ --i;
+ }
+ continue;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ if ( !(nMode & IDocumentContentOperations::INS_NOHINTEXPAND) &&
+ rIdx == nLen && *pHt->GetStart() == rIdx.GetIndex() &&
+ !pHt->IsDontExpandStartAttr() )
+ {
+ // Kein Feld, am Absatzanfang, HintExpand
+ m_pSwpHints->DeleteAtPos(i);
+ *pHt->GetStart() = *pHt->GetStart() - nLen;
+ InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+ }
+ TryDeleteSwpHints();
+ }
+
+ if ( GetDepends() )
+ {
+ SwInsTxt aHint( aPos, nLen );
+ SwModify::Modify( 0, &aHint );
+ }
+
+ // By inserting a character, the hidden flags
+ // at the TxtNode can become invalid:
+ SetCalcHiddenCharFlags();
+
+ CHECK_SWPHINTS(this);
+}
+
+/*************************************************************************
+|*
+|* SwTxtNode::Cut()
+|*
+|* Beschreibung text.doc
+|* Ersterstellung VB 20.03.91
+|* Letzte Aenderung JP 11.08.94
+|*
+*************************************************************************/
+
+void SwTxtNode::CutText( SwTxtNode * const pDest,
+ const SwIndex & rStart, const xub_StrLen nLen )
+{
+ if(pDest)
+ {
+ SwIndex aDestStt( pDest, pDest->GetTxt().Len() );
+ CutImpl( pDest, aDestStt, rStart, nLen, false );
+ }
+ else
+ {
+ ASSERT(false,
+ "mst: entering dead and bitrotted code; fasten your seatbelts!");
+ EraseText( rStart, nLen );
+ }
+}
+
+
+void SwTxtNode::CutImpl( SwTxtNode * const pDest, const SwIndex & rDestStart,
+ const SwIndex & rStart, /*const*/ xub_StrLen nLen, const bool bUpdate )
+{
+ if(!pDest)
+ {
+ ASSERT(false,
+ "mst: entering dead and bitrotted code; fasten your seatbelts!");
+ EraseText( rStart, nLen );
+ return;
+ }
+
+ // nicht im Dokument verschieben ?
+ if( GetDoc() != pDest->GetDoc() )
+ {
+ ASSERT(false,
+ "mst: entering dead and bitrotted code; fasten your seatbelts!");
+ CopyText( pDest, rDestStart, rStart, nLen);
+ EraseText(rStart, nLen);
+ return;
+ }
+
+ if( !nLen )
+ {
+ // wurde keine Laenge angegeben, dann Kopiere die Attribute
+ // an der Position rStart.
+ CopyAttr( pDest, rStart.GetIndex(), rDestStart.GetIndex() );
+ return;
+ }
+
+ xub_StrLen nTxtStartIdx = rStart.GetIndex();
+ xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken
+ const xub_StrLen nInitSize = pDest->m_Text.Len();
+
+ // wird in sich selbst verschoben, muss es gesondert behandelt werden !!
+ if( pDest == this )
+ {
+ ASSERT(false,
+ "mst: entering dead and bitrotted code; fasten your seatbelts!");
+ m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart );
+ m_Text.Erase( nTxtStartIdx + (nDestStart<nTxtStartIdx ? nLen : 0), nLen );
+
+ const xub_StrLen nEnd = rStart.GetIndex() + nLen;
+
+ // dann suche mal alle Attribute zusammen, die im verschobenen
+ // Bereich liegen. Diese werden in das extra Array verschoben,
+ // damit sich die Indizies beim Updaten nicht veraendern !!!
+ SwpHts aArr( 5 );
+
+ // 2. Attribute verschieben
+ // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
+ // des Attributs hinter dem zu verschiebenden Bereich liegt
+ USHORT nAttrCnt = 0;
+ while ( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
+ const xub_StrLen nAttrStartIdx = *pHt->GetStart();
+ if (!( nAttrStartIdx < nEnd ))
+ break;
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ const USHORT nWhich = pHt->Which();
+ SwTxtAttr *pNewHt = 0;
+
+ if(nAttrStartIdx < nTxtStartIdx)
+ {
+ // Anfang liegt vor dem Bereich
+ if ( RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar() &&
+ pEndIdx && *pEndIdx > nTxtStartIdx )
+ {
+ // Attribut mit einem Bereich
+ // und das Ende des Attribut liegt im Bereich
+ pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 0,
+ *pEndIdx > nEnd
+ ? nLen
+ : *pEndIdx - nTxtStartIdx );
+ }
+ }
+ else
+ {
+ // der Anfang liegt vollstaendig im Bereich
+ if( !pEndIdx || *pEndIdx < nEnd )
+ {
+ // Attribut verschieben
+ m_pSwpHints->Delete( pHt );
+ // die Start/End Indicies neu setzen
+ *pHt->GetStart() = nAttrStartIdx - nTxtStartIdx;
+ if( pEndIdx )
+ *pHt->GetEnd() = *pEndIdx - nTxtStartIdx;
+ aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() );
+ continue; // while-Schleife weiter, ohne ++ !
+ }
+ // das Ende liegt dahinter
+ else if (RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar())
+ {
+ pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
+ nAttrStartIdx - nTxtStartIdx,
+ !pEndIdx ? 0
+ : ( *pEndIdx > nEnd
+ ? nLen
+ : *pEndIdx - nTxtStartIdx ));
+ }
+ }
+ if( pNewHt )
+ {
+ // die Daten kopieren
+ lcl_CopyHint( nWhich, pHt, pNewHt, 0, this );
+ aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() );
+ }
+ ++nAttrCnt;
+ }
+
+ if( bUpdate )
+ {
+ // Update aller Indizies
+ Update( rDestStart, nLen, FALSE, TRUE );
+ }
+#ifdef CUTNOEXPAND
+ else
+ // wird am Ende eingefuegt, nur die Attribut-Indizies verschieben
+ if ( 0 < nLen && 0 < nInitSize && m_pSwpHints )
+ {
+ // check if there was the end of an attribute at the insertion
+ // position: if it is not a field, it must be expanded
+ for ( USHORT n = 0; n < m_pSwpHints->Count(); n++ )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n);
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ if ( pEndIdx && (*pEndIdx == nInitSize) )
+ {
+ *pEndIdx = *pEndIdx + nLen;
+ }
+ }
+ }
+#endif
+ CHECK_SWPHINTS(this);
+
+ Update( rStart, nLen, TRUE, TRUE );
+
+ CHECK_SWPHINTS(this);
+
+ // dann setze die kopierten/geloeschten Attribute in den Node
+ if( nDestStart <= nTxtStartIdx )
+ {
+ nTxtStartIdx = nTxtStartIdx + nLen;
+ }
+ else
+ {
+ nDestStart = nDestStart - nLen;
+ }
+
+ for ( USHORT n = 0; n < aArr.Count(); ++n )
+ {
+ SwTxtAttr *const pNewHt = aArr[n];
+ *pNewHt->GetStart() = nDestStart + *pNewHt->GetStart();
+ xub_StrLen * const pEndIdx = pNewHt->GetEnd();
+ if ( pEndIdx )
+ {
+ *pEndIdx = nDestStart + *pEndIdx;
+ }
+ InsertHint( pNewHt, nsSetAttrMode::SETATTR_NOTXTATRCHR );
+ }
+ }
+ else
+ {
+ pDest->m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart );
+ m_Text.Erase( nTxtStartIdx, nLen );
+ nLen = pDest->m_Text.Len() - nInitSize; // update w/ current size!
+ if( !nLen ) // String nicht gewachsen ??
+ return;
+
+ if( bUpdate )
+ {
+ // Update aller Indizies
+ pDest->Update( rDestStart, nLen, FALSE, TRUE);
+ }
+#ifdef CUTNOEXPAND
+ else
+ // wird am Ende eingefuegt, nur die Attribut-Indizies verschieben
+ if ( 0 < nLen && 0 < nInitSize && pDest->m_pSwpHints )
+ {
+ // check if there was the end of an attribute at the insertion
+ // position: if it is not a field, it must be expanded
+ for ( USHORT n = 0; n < pDest->m_pSwpHints->Count(); n++ )
+ {
+ SwTxtAttr * const pHt = pDest->m_pSwpHints->GetTextHint(n);
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ if ( pEndIdx && (*pEndIdx == nInitSize) )
+ {
+ *pEndIdx = *pEndIdx + nLen;
+ }
+ }
+ }
+#endif
+ CHECK_SWPHINTS(pDest);
+
+ const xub_StrLen nEnd = rStart.GetIndex() + nLen;
+ SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc())
+ ? pDest->GetDoc() : 0;
+ const bool bUndoNodes =
+ !pOtherDoc && GetDoc()->GetUndoNds() == &GetNodes();
+
+ ASSERT(!pOtherDoc,
+ "mst: entering dead and bitrotted code; fasten your seatbelts!");
+
+ // harte Absatz umspannende Attribute kopieren
+ if( HasSwAttrSet() )
+ {
+ // alle, oder nur die CharAttribute ?
+ if( nInitSize || pDest->HasSwAttrSet() ||
+ nLen != pDest->GetTxt().Len() )
+ {
+ SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+ aCharSet.Put( *GetpSwAttrSet() );
+ if( aCharSet.Count() )
+ pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
+ }
+ else
+ {
+ GetpSwAttrSet()->CopyToModify( *pDest );
+ }
+ }
+
+ // 2. Attribute verschieben
+ // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
+ // des Attributs hinter dem zu verschiebenden Bereich liegt
+ USHORT nAttrCnt = 0;
+ while ( m_pSwpHints && (nAttrCnt < m_pSwpHints->Count()) )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
+ const xub_StrLen nAttrStartIdx = *pHt->GetStart();
+ if (!( nAttrStartIdx < nEnd ))
+ break;
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ const USHORT nWhich = pHt->Which();
+ SwTxtAttr *pNewHt = 0;
+
+ // if the hint has a dummy character, then it must not be split!
+ if(nAttrStartIdx < nTxtStartIdx)
+ {
+ // Anfang liegt vor dem Bereich
+ if( !pHt->HasDummyChar() && ( RES_TXTATR_REFMARK != nWhich
+ || bUndoNodes ) && pEndIdx && *pEndIdx > nTxtStartIdx )
+ {
+ // Attribut mit einem Bereich
+ // und das Ende des Attribut liegt im Bereich
+ pNewHt = MakeTxtAttr( *pDest->GetDoc(), pHt->GetAttr(),
+ nDestStart,
+ nDestStart + (
+ *pEndIdx > nEnd
+ ? nLen
+ : *pEndIdx - nTxtStartIdx ) );
+ }
+ }
+ else
+ {
+ // der Anfang liegt vollstaendig im Bereich
+ if( !pEndIdx || *pEndIdx < nEnd ||
+ (!pOtherDoc && !bUndoNodes && RES_TXTATR_REFMARK == nWhich)
+ || pHt->HasDummyChar() )
+ {
+ // do not delete note and later add it -> sidebar flickering
+ if ( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
+ }
+ // Attribut verschieben
+ m_pSwpHints->Delete( pHt );
+ // die Start/End Indicies neu setzen
+ *pHt->GetStart() =
+ nDestStart + (nAttrStartIdx - nTxtStartIdx);
+ if( pEndIdx )
+ {
+ *pHt->GetEnd() = nDestStart + (
+ *pEndIdx > nEnd
+ ? nLen
+ : *pEndIdx - nTxtStartIdx );
+ }
+ pDest->InsertHint( pHt,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR
+ | nsSetAttrMode::SETATTR_DONTREPLACE );
+ if ( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
+ }
+ continue; // while-Schleife weiter, ohne ++ !
+ }
+ // das Ende liegt dahinter
+ else if( RES_TXTATR_REFMARK != nWhich || bUndoNodes )
+ {
+ pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
+ nDestStart + (nAttrStartIdx - nTxtStartIdx),
+ !pEndIdx ? 0
+ : nDestStart + ( *pEndIdx > nEnd
+ ? nLen
+ : *pEndIdx - nTxtStartIdx ));
+ }
+ }
+ if ( pNewHt )
+ {
+ const bool bSuccess( pDest->InsertHint( pNewHt,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR
+ | nsSetAttrMode::SETATTR_DONTREPLACE ) );
+ if (bSuccess)
+ {
+ lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
+ }
+ }
+ ++nAttrCnt;
+ }
+ // sollten jetzt noch leere Attribute rumstehen, dann haben diese
+ // eine hoehere Praezedenz. Also herausholen und das Array updaten.
+ // Die dabei entstehenden leeren Hints werden von den gesicherten
+ // "uebergeplaettet". (Bug: 6977)
+ if( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
+ {
+ SwpHts aArr( 5 );
+ while ( nAttrCnt < m_pSwpHints->Count() )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
+ if ( nEnd != *pHt->GetStart() )
+ break;
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ if ( pEndIdx && *pEndIdx == nEnd )
+ {
+ aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() );
+ m_pSwpHints->Delete( pHt );
+ }
+ else
+ {
+ ++nAttrCnt;
+ }
+ }
+ Update( rStart, nLen, TRUE, TRUE );
+
+ for ( USHORT n = 0; n < aArr.Count(); ++n )
+ {
+ SwTxtAttr * const pHt = aArr[ n ];
+ *pHt->GetStart() = *pHt->GetEnd() = rStart.GetIndex();
+ InsertHint( pHt );
+ }
+ }
+ else
+ {
+ Update( rStart, nLen, TRUE, TRUE );
+ }
+
+ CHECK_SWPHINTS(this);
+ }
+
+ TryDeleteSwpHints();
+
+ // Frames benachrichtigen;
+ SwInsTxt aInsHint( nDestStart, nLen );
+ pDest->Modify( 0, &aInsHint );
+ SwDelTxt aDelHint( nTxtStartIdx, nLen );
+ Modify( 0, &aDelHint );
+}
+
+
+void SwTxtNode::EraseText(const SwIndex &rIdx, const xub_StrLen nCount,
+ const IDocumentContentOperations::InsertFlags nMode )
+{
+ ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::EraseText: invalid index." );
+
+ const xub_StrLen nStartIdx = rIdx.GetIndex();
+ const xub_StrLen nCnt = (STRING_LEN == nCount)
+ ? m_Text.Len() - nStartIdx : nCount;
+ const xub_StrLen nEndIdx = nStartIdx + nCnt;
+ m_Text.Erase( nStartIdx, nCnt );
+
+ /* GCAttr(); alle leeren weggwerfen ist zu brutal.
+ * Es duerfen nur die wegggeworfen werden,
+ * die im Bereich liegen und nicht am Ende des Bereiches liegen
+ */
+
+ for ( USHORT i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
+ {
+ SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);
+
+ const xub_StrLen nHintStart = *pHt->GetStart();
+
+ if ( nHintStart < nStartIdx )
+ continue;
+
+ if ( nHintStart > nEndIdx )
+ break; // hints are sorted by end, so break here
+
+ const xub_StrLen* pHtEndIdx = pHt->GetEnd();
+ const USHORT nWhich = pHt->Which();
+
+ if( !pHtEndIdx )
+ {
+ ASSERT(pHt->HasDummyChar(),
+ "attribute with neither end nor CH_TXTATR?");
+ if (isTXTATR(nWhich) &&
+ (nHintStart >= nStartIdx) && (nHintStart < nEndIdx))
+ {
+ m_pSwpHints->DeleteAtPos(i);
+ DestroyAttr( pHt );
+ --i;
+ }
+ continue;
+ }
+
+ ASSERT (!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx)
+ && pHt->HasDummyChar() )
+ // next line: deleting exactly dummy char: DeleteAttributes
+ || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx)),
+ "ERROR: deleting left-overlapped attribute with CH_TXTATR");
+
+ // Delete the hint if:
+ // 1. The hint ends before the deletion end position or
+ // 2. The hint ends at the deletion end position and
+ // we are not in empty expand mode and
+ // the hint is a [toxmark|refmark|ruby] text attribute
+ // 3. deleting exactly the dummy char of an hint with end and dummy
+ // char deletes the hint
+ if ( (*pHtEndIdx < nEndIdx)
+ || ( (*pHtEndIdx == nEndIdx) &&
+ !(IDocumentContentOperations::INS_EMPTYEXPAND & nMode) &&
+ ( (RES_TXTATR_TOXMARK == nWhich) ||
+ (RES_TXTATR_REFMARK == nWhich) ||
+ // --> FME 2006-03-03 #i62668# Ruby text attribute must be
+ // treated just like toxmark and refmarks
+ (RES_TXTATR_CJK_RUBY == nWhich) ) )
+ // <--
+#if 0
+ || ( (nHintStart == nStartIdx) &&
+ (nHintStart + 1 == nEndIdx)&&
+#else // generalize this to left-overlapped dummy char hints (see ASSERT)
+ || ( (nHintStart < nEndIdx) &&
+#endif
+ pHt->HasDummyChar() )
+ )
+ {
+ m_pSwpHints->DeleteAtPos(i);
+ DestroyAttr( pHt );
+ --i;
+ }
+ }
+
+ ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
+
+ TryDeleteSwpHints();
+
+ Update( rIdx, nCnt, TRUE );
+
+ if( 1 == nCnt )
+ {
+ SwDelChr aHint( nStartIdx );
+ SwModify::Modify( 0, &aHint );
+ }
+ else
+ {
+ SwDelTxt aHint( nStartIdx, nCnt );
+ SwModify::Modify( 0, &aHint );
+ }
+
+ ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
+
+ // By deleting a character, the hidden flags
+ // at the TxtNode can become invalid:
+ SetCalcHiddenCharFlags();
+
+ CHECK_SWPHINTS(this);
+}
+
+/***********************************************************************
+#* Class : SwTxtNode
+#* Methode : GCAttr
+#*
+#* Beschreibung
+#* text.doc
+#*
+#* Datum : MS 28.11.90
+#* Update : VB 24.07.91
+#***********************************************************************/
+
+void SwTxtNode::GCAttr()
+{
+ if ( !HasHints() )
+ return;
+
+ bool bChanged = false;
+ USHORT nMin = m_Text.Len(),
+ nMax = 0;
+ BOOL bAll = nMin != 0; // Bei leeren Absaetzen werden nur die
+ // INet-Formate entfernt.
+
+ for ( USHORT i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(i);
+
+ // wenn Ende und Start gleich sind --> loeschen
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ if (pEndIdx && !pHt->HasDummyChar() && (*pEndIdx == *pHt->GetStart())
+ && ( bAll || pHt->Which() == RES_TXTATR_INETFMT ) )
+ {
+ bChanged = true;
+ nMin = Min( nMin, *pHt->GetStart() );
+ nMax = Max( nMax, *pHt->GetEnd() );
+ DestroyAttr( m_pSwpHints->Cut(i) );
+ --i;
+ }
+ else
+ {
+ pHt->SetDontExpand( false );
+ }
+ }
+ TryDeleteSwpHints();
+
+ if(bChanged)
+ {
+ //TxtFrm's reagieren auf aHint, andere auf aNew
+ SwUpdateAttr aHint( nMin, nMax, 0 );
+ SwModify::Modify( 0, &aHint );
+ SwFmtChg aNew( GetTxtColl() );
+ SwModify::Modify( 0, &aNew );
+ }
+}
+
+// #i23726#
+SwNumRule* SwTxtNode::_GetNumRule(BOOL bInParent) const
+{
+ SwNumRule* pRet = 0;
+
+ const SfxPoolItem* pItem = GetNoCondAttr( RES_PARATR_NUMRULE, bInParent );
+ bool bNoNumRule = false;
+ if ( pItem )
+ {
+ String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue();
+ if (sNumRuleName.Len() > 0)
+ {
+ pRet = GetDoc()->FindNumRulePtr( sNumRuleName );
+ }
+ else // numbering is turned off
+ bNoNumRule = true;
+ }
+
+ if ( !bNoNumRule )
+ {
+ if ( pRet && pRet == GetDoc()->GetOutlineNumRule() &&
+ ( !HasSwAttrSet() ||
+ SFX_ITEM_SET !=
+ GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, FALSE ) ) )
+ {
+ SwTxtFmtColl* pColl = GetTxtColl();
+ if ( pColl )
+ {
+ const SwNumRuleItem& rDirectItem = pColl->GetNumRule( FALSE );
+ if ( rDirectItem.GetValue().Len() == 0 )
+ {
+ pRet = 0L;
+ }
+ }
+ }
+
+ // --> OD 2006-11-20 #i71764#
+ // Document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE has no influence
+ // any more.
+// if ( !pRet &&
+// GetDoc()->get(IDocumentSettingAccess::OUTLINE_LEVEL_YIELDS_OUTLINE_RULE) &&
+// GetOutlineLevel() != NO_NUMBERING )
+// {
+// pRet = GetDoc()->GetOutlineNumRule();
+// }
+ // <--
+ }
+ // old code before tuning
+// // --> OD 2005-10-25 #126347#
+// // determine of numbering/bullet rule, which is set as a hard attribute
+// // at the text node
+// const SfxPoolItem* pItem( 0L );
+// if ( HasSwAttrSet() ) // does text node has hard attributes ?
+// {
+// if ( SFX_ITEM_SET !=
+// GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, FALSE, &pItem ) )
+// {
+// pItem = 0L;
+// }
+// // else: <pItem> contains the numbering/bullet attribute, which is
+// // hard set at the paragraph.
+
+// }
+// // <--
+// bool bNoNumRule = false;
+// if (pItem)
+// {
+// String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue();
+// if (sNumRuleName.Len() > 0)
+// {
+// pRet = GetDoc()->FindNumRulePtr(sNumRuleName);
+// }
+// else // numbering is turned off by hard attribute
+// bNoNumRule = true;
+// }
+
+// if (! bNoNumRule)
+// {
+// if (! pRet && bInParent)
+// {
+// SwTxtFmtColl * pColl = GetTxtColl();
+
+// if (pColl)
+// {
+// const SwNumRuleItem & rItem = pColl->GetNumRule(TRUE);
+
+// pRet = const_cast<SwDoc *>(GetDoc())->
+// FindNumRulePtrWithPool(rItem.GetValue());
+// // --> OD 2005-10-13 #125993# - The outline numbering rule
+// // isn't allowed to be derived from a parent paragraph style
+// // to a derived one.
+// // Thus check, if the found outline numbering rule is directly
+// // set at the paragraph style <pColl>. If not, don't return
+// // the outline numbering rule.
+// if ( pRet && pRet == GetDoc()->GetOutlineNumRule() )
+// {
+// const SwNumRuleItem& rDirectItem = pColl->GetNumRule(FALSE);
+// SwNumRule* pNumRuleAtParaStyle = const_cast<SwDoc*>(GetDoc())->
+// FindNumRulePtrWithPool(rDirectItem.GetValue());
+// if ( !pNumRuleAtParaStyle )
+// {
+// pRet = 0L;
+// }
+// }
+// // <--
+// }
+// }
+
+// if (!pRet && GetDoc()->IsOutlineLevelYieldsOutlineRule() &&
+// GetOutlineLevel() != NO_NUMBERING)
+// pRet = GetDoc()->GetOutlineNumRule();
+// }
+ // <--
+
+ return pRet;
+}
+
+SwNumRule* SwTxtNode::GetNumRule(BOOL bInParent) const
+{
+ SwNumRule * pRet = _GetNumRule(bInParent);
+
+ return pRet;
+}
+
+void SwTxtNode::NumRuleChgd()
+{
+ // --> OD 2008-04-04 #refactorlists#
+ if ( IsInList() )
+ {
+ SwNumRule* pNumRule = GetNumRule();
+ if ( pNumRule && pNumRule != GetNum()->GetNumRule() )
+ {
+ mpNodeNum->ChangeNumRule( *pNumRule );
+ }
+ }
+ // <--
+
+ if( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( FALSE );
+ }
+ SetInSwFntCache( FALSE );
+
+ SvxLRSpaceItem& rLR = (SvxLRSpaceItem&)GetSwAttrSet().GetLRSpace();
+
+ SwModify::Modify( &rLR, &rLR );
+}
+
+// -> #i27615#
+BOOL SwTxtNode::IsNumbered() const
+{
+ BOOL bResult = FALSE;
+
+ SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule && IsCountedInList() )
+ bResult = TRUE;
+
+ return bResult;
+}
+
+// --> OD 2008-04-02 #refactorlists#
+bool SwTxtNode::HasMarkedLabel() const
+{
+ bool bResult = false;
+
+ if ( IsInList() )
+ {
+ bResult =
+ GetDoc()->getListByName( GetListId() )->IsListLevelMarked( GetActualListLevel() );
+ }
+
+ return bResult;
+}
+// <--
+// <- #i27615#
+
+SwTxtNode* SwTxtNode::_MakeNewTxtNode( const SwNodeIndex& rPos, BOOL bNext,
+ BOOL bChgFollow )
+{
+ /* hartes PageBreak/PageDesc/ColumnBreak aus AUTO-Set ignorieren */
+ SwAttrSet* pNewAttrSet = 0;
+ // --> OD 2007-07-10 #i75353#
+ bool bClearHardSetNumRuleWhenFmtCollChanges( false );
+ // <--
+ if( HasSwAttrSet() )
+ {
+ pNewAttrSet = new SwAttrSet( *GetpSwAttrSet() );
+ const SfxItemSet* pTmpSet = GetpSwAttrSet();
+
+ if( bNext ) // der naechste erbt keine Breaks!
+ pTmpSet = pNewAttrSet;
+
+ // PageBreaks/PageDesc/ColBreak rausschmeissen.
+ BOOL bRemoveFromCache = FALSE;
+ std::vector<USHORT> aClearWhichIds;
+ if ( bNext )
+ bRemoveFromCache = ( 0 != pNewAttrSet->ClearItem( RES_PAGEDESC ) );
+ else
+ aClearWhichIds.push_back( RES_PAGEDESC );
+
+ if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_BREAK, FALSE ) )
+ {
+ if ( bNext )
+ pNewAttrSet->ClearItem( RES_BREAK );
+ else
+ aClearWhichIds.push_back( RES_BREAK );
+ bRemoveFromCache = TRUE;
+ }
+ if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_KEEP, FALSE ) )
+ {
+ if ( bNext )
+ pNewAttrSet->ClearItem( RES_KEEP );
+ else
+ aClearWhichIds.push_back( RES_KEEP );
+ bRemoveFromCache = TRUE;
+ }
+ if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_PARATR_SPLIT, FALSE ) )
+ {
+ if ( bNext )
+ pNewAttrSet->ClearItem( RES_PARATR_SPLIT );
+ else
+ aClearWhichIds.push_back( RES_PARATR_SPLIT );
+ bRemoveFromCache = TRUE;
+ }
+ if(SFX_ITEM_SET == pTmpSet->GetItemState(RES_PARATR_NUMRULE, FALSE))
+ {
+ SwNumRule * pRule = GetNumRule();
+
+ if (pRule && IsOutline())
+ {
+ if ( bNext )
+ pNewAttrSet->ClearItem(RES_PARATR_NUMRULE);
+ else
+ {
+ // --> OD 2007-07-10 #i75353#
+ // No clear of hard set numbering rule at an outline paragraph at this point.
+ // Only if the paragraph style changes - see below.
+// aClearWhichIds.push_back( RES_PARATR_NUMRULE );
+ bClearHardSetNumRuleWhenFmtCollChanges = true;
+ // <--
+ }
+ bRemoveFromCache = TRUE;
+ }
+ }
+
+ if ( 0 != aClearWhichIds.size() )
+ bRemoveFromCache = 0 != ClearItemsFromAttrSet( aClearWhichIds );
+
+ if( !bNext && bRemoveFromCache && IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( FALSE );
+ }
+ }
+ SwNodes& rNds = GetNodes();
+
+ SwTxtFmtColl* pColl = GetTxtColl();
+
+ SwTxtNode *pNode = new SwTxtNode( rPos, pColl, pNewAttrSet );
+
+ if( pNewAttrSet )
+ delete pNewAttrSet;
+
+ const SwNumRule* pRule = GetNumRule();
+ if( pRule && pRule == pNode->GetNumRule() && rNds.IsDocNodes() ) // #115901#
+ {
+ // --> OD 2005-10-18 #i55459#
+ // - correction: parameter <bNext> has to be checked, as it was in the
+ // previous implementation.
+ if ( !bNext && !IsCountedInList() )
+ SetCountedInList(true);
+ // <--
+ }
+
+ // jetzt kann es sein, das durch die Nummerierung dem neuen Node eine
+ // Vorlage aus dem Pool zugewiesen wurde. Dann darf diese nicht
+ // nochmal uebergeplaettet werden !!
+ if( pColl != pNode->GetTxtColl() ||
+ ( bChgFollow && pColl != GetTxtColl() ))
+ return pNode; // mehr duerfte nicht gemacht werden oder ????
+
+ pNode->_ChgTxtCollUpdateNum( 0, pColl ); // fuer Nummerierung/Gliederung
+ if( bNext || !bChgFollow )
+ return pNode;
+
+ SwTxtFmtColl *pNextColl = &pColl->GetNextTxtFmtColl();
+ // --> OD 2009-08-12 #i101870#
+ // perform action on different paragraph styles before applying the new paragraph style
+ if (pNextColl != pColl)
+ {
+ // --> OD 2007-07-10 #i75353#
+ if ( bClearHardSetNumRuleWhenFmtCollChanges )
+ {
+ std::vector<USHORT> aClearWhichIds;
+ aClearWhichIds.push_back( RES_PARATR_NUMRULE );
+ if ( ClearItemsFromAttrSet( aClearWhichIds ) != 0 && IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( FALSE );
+ }
+ }
+ // <--
+ }
+ // <--
+ ChgFmtColl( pNextColl );
+
+ return pNode;
+}
+
+SwCntntNode* SwTxtNode::AppendNode( const SwPosition & rPos )
+{
+ // Position hinter dem eingefuegt wird
+ SwNodeIndex aIdx( rPos.nNode, 1 );
+ SwTxtNode* pNew = _MakeNewTxtNode( aIdx, TRUE );
+
+ // --> OD 2008-05-14 #refactorlists#
+ // reset list attributes at appended text node
+ pNew->ResetAttr( RES_PARATR_LIST_ISRESTART );
+ pNew->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
+ pNew->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
+ if ( pNew->GetNumRule() == 0 )
+ {
+ pNew->ResetAttr( RES_PARATR_LIST_ID );
+ pNew->ResetAttr( RES_PARATR_LIST_LEVEL );
+ }
+ // <--
+ // --> OD 2008-03-13 #refactorlists#
+// SyncNumberAndNumRule();
+ if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
+ {
+ AddToList();
+ }
+ // <--
+
+ if( GetDepends() )
+ MakeFrms( *pNew );
+ return pNew;
+}
+
+/*************************************************************************
+ * SwTxtNode::GetTxtAttr
+ *************************************************************************/
+
+SwTxtAttr * SwTxtNode::GetTxtAttrForCharAt( const xub_StrLen nIndex,
+ const RES_TXTATR nWhich ) const
+{
+ if ( HasHints() )
+ {
+ for ( USHORT i = 0; i < m_pSwpHints->Count(); ++i )
+ {
+ SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(i);
+ const xub_StrLen nStartPos = *pHint->GetStart();
+ if ( nIndex < nStartPos )
+ {
+ return 0;
+ }
+ if ( (nIndex == nStartPos) && pHint->HasDummyChar() )
+ {
+ return ( RES_TXTATR_END == nWhich || nWhich == pHint->Which() )
+ ? pHint : 0;
+ }
+ }
+ }
+ return 0;
+}
+
+// -> #i29560#
+BOOL SwTxtNode::HasNumber() const
+{
+ BOOL bResult = FALSE;
+
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule )
+ {
+ SwNumFmt aFmt(pRule->Get( static_cast<USHORT>(GetActualListLevel())));
+
+ // #i40041#
+ bResult = aFmt.IsEnumeration() &&
+ SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType();
+ }
+
+ return bResult;
+}
+
+BOOL SwTxtNode::HasBullet() const
+{
+ BOOL bResult = FALSE;
+
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule )
+ {
+ SwNumFmt aFmt(pRule->Get( static_cast<USHORT>(GetActualListLevel())));
+
+ bResult = aFmt.IsItemize();
+ }
+
+ return bResult;
+}
+// <- #i29560#
+
+// --> OD 2005-11-17 #128041# - introduce parameter <_bInclPrefixAndSuffixStrings>
+//i53420 added max outline parameter
+XubString SwTxtNode::GetNumString( const bool _bInclPrefixAndSuffixStrings, const unsigned int _nRestrictToThisLevel ) const
+{
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule &&
+ IsCountedInList() &&
+ pRule->Get( static_cast<USHORT>(GetActualListLevel()) ).IsTxtFmt() )
+ {
+ return pRule->MakeNumString( GetNum()->GetNumberVector(),
+ _bInclPrefixAndSuffixStrings ? TRUE : FALSE,
+ FALSE,
+ _nRestrictToThisLevel );
+ }
+
+ return aEmptyStr;
+}
+
+long SwTxtNode::GetLeftMarginWithNum( BOOL bTxtLeft ) const
+{
+ long nRet = 0;
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if( pRule )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<USHORT>(GetActualListLevel()));
+ // --> OD 2008-01-16 #newlistlevelattrs#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ nRet = rFmt.GetAbsLSpace();
+
+ if( !bTxtLeft )
+ {
+ if( 0 > rFmt.GetFirstLineOffset() &&
+ nRet > -rFmt.GetFirstLineOffset() )
+ nRet = nRet + rFmt.GetFirstLineOffset();
+ else
+ nRet = 0;
+ }
+
+ if( pRule->IsAbsSpaces() )
+ nRet = nRet - GetSwAttrSet().GetLRSpace().GetLeft();
+ }
+ else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ if ( AreListLevelIndentsApplicable() )
+ {
+ nRet = rFmt.GetIndentAt();
+ // --> OD 2008-06-06 #i90401#
+ // Only negative first line indents have consider for the left margin
+ if ( !bTxtLeft &&
+ rFmt.GetFirstLineIndent() < 0 )
+ {
+ nRet = nRet + rFmt.GetFirstLineIndent();
+ }
+ // <--
+ }
+ }
+ // <--
+ }
+
+ return nRet;
+}
+
+BOOL SwTxtNode::GetFirstLineOfsWithNum( short& rFLOffset ) const
+{
+ BOOL bRet( FALSE );
+ // --> OD 2009-09-08 #i95907#, #b6879723#
+ rFLOffset = 0;
+ // <--
+
+ // --> OD 2005-11-02 #i51089 - TUNING#
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule )
+ {
+ if ( IsCountedInList() )
+ {
+ // --> OD 2008-01-16 #newlistlevelattrs#
+ const SwNumFmt& rFmt = pRule->Get(static_cast<USHORT>(GetActualListLevel()));
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ rFLOffset = pRule->Get( static_cast<USHORT>(GetActualListLevel() )).GetFirstLineOffset();
+
+ if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
+ {
+ SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
+ rFLOffset = rFLOffset + aItem.GetTxtFirstLineOfst();
+ }
+ }
+ else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ if ( AreListLevelIndentsApplicable() )
+ {
+ rFLOffset = static_cast<USHORT>(rFmt.GetFirstLineIndent());
+ }
+ else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
+ {
+ SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
+ rFLOffset = aItem.GetTxtFirstLineOfst();
+ }
+ }
+ // <--
+ }
+
+ bRet = TRUE;
+ }
+ else
+ {
+ rFLOffset = GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
+ }
+
+ return bRet;
+}
+
+// --> OD 2008-12-02 #i96772#
+void SwTxtNode::ClearLRSpaceItemDueToListLevelIndents( SvxLRSpaceItem& o_rLRSpaceItem ) const
+{
+ if ( AreListLevelIndentsApplicable() )
+ {
+ const SwNumRule* pRule = GetNumRule();
+ if ( pRule && GetActualListLevel() >= 0 )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<USHORT>(GetActualListLevel()));
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ o_rLRSpaceItem = aLR;
+ }
+ }
+ }
+}
+// <--
+
+// --> OD 2008-07-01 #i91133#
+long SwTxtNode::GetLeftMarginForTabCalculation() const
+{
+ long nLeftMarginForTabCalc = 0;
+
+ bool bLeftMarginForTabCalcSetToListLevelIndent( false );
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0;
+ if( pRule )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<USHORT>(GetActualListLevel()));
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ if ( AreListLevelIndentsApplicable() )
+ {
+ nLeftMarginForTabCalc = rFmt.GetIndentAt();
+ bLeftMarginForTabCalcSetToListLevelIndent = true;
+ }
+ }
+ }
+ if ( !bLeftMarginForTabCalcSetToListLevelIndent )
+ {
+ nLeftMarginForTabCalc = GetSwAttrSet().GetLRSpace().GetTxtLeft();
+ }
+
+ return nLeftMarginForTabCalc;
+}
+// <--
+
+void SwTxtNode::Replace0xFF( XubString& rTxt, xub_StrLen& rTxtStt,
+ xub_StrLen nEndPos, BOOL bExpandFlds ) const
+{
+ if( GetpSwpHints() )
+ {
+ sal_Unicode cSrchChr = CH_TXTATR_BREAKWORD;
+ for( int nSrchIter = 0; 2 > nSrchIter; ++nSrchIter,
+ cSrchChr = CH_TXTATR_INWORD )
+ {
+ xub_StrLen nPos = rTxt.Search( cSrchChr );
+ while( STRING_NOTFOUND != nPos && nPos < nEndPos )
+ {
+ const SwTxtAttr* const pAttr =
+ GetTxtAttrForCharAt( rTxtStt + nPos );
+ if( pAttr )
+ {
+ switch( pAttr->Which() )
+ {
+ case RES_TXTATR_FIELD:
+ rTxt.Erase( nPos, 1 );
+ if( bExpandFlds )
+ {
+ const XubString aExpand( ((SwTxtFld*)pAttr)->GetFld().
+ GetFld()->Expand() );
+ rTxt.Insert( aExpand, nPos );
+ nPos = nPos + aExpand.Len();
+ nEndPos = nEndPos + aExpand.Len();
+ rTxtStt = rTxtStt - aExpand.Len();
+ }
+ ++rTxtStt;
+ break;
+ case RES_TXTATR_FTN:
+ rTxt.Erase( nPos, 1 );
+ if( bExpandFlds )
+ {
+ const SwFmtFtn& rFtn = pAttr->GetFtn();
+ XubString sExpand;
+ if( rFtn.GetNumStr().Len() )
+ sExpand = rFtn.GetNumStr();
+ else if( rFtn.IsEndNote() )
+ sExpand = GetDoc()->GetEndNoteInfo().aFmt.
+ GetNumStr( rFtn.GetNumber() );
+ else
+ sExpand = GetDoc()->GetFtnInfo().aFmt.
+ GetNumStr( rFtn.GetNumber() );
+ rTxt.Insert( sExpand, nPos );
+ nPos = nPos + sExpand.Len();
+ nEndPos = nEndPos + sExpand.Len();
+ rTxtStt = rTxtStt - sExpand.Len();
+ }
+ ++rTxtStt;
+ break;
+ default:
+ rTxt.Erase( nPos, 1 );
+ ++rTxtStt;
+ }
+ }
+ else
+ ++nPos, ++nEndPos;
+ nPos = rTxt.Search( cSrchChr, nPos );
+ }
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtNode::GetExpandTxt
+ * Expand fields
+ *************************************************************************/
+// --> OD 2007-11-15 #i83479# - handling of new parameters
+XubString SwTxtNode::GetExpandTxt( const xub_StrLen nIdx,
+ const xub_StrLen nLen,
+ const bool bWithNum,
+ const bool bAddSpaceAfterListLabelStr,
+ const bool bWithSpacesForLevel ) const
+{
+ XubString aTxt( GetTxt().Copy( nIdx, nLen ) );
+ xub_StrLen nTxtStt = nIdx;
+ Replace0xFF( aTxt, nTxtStt, aTxt.Len(), TRUE );
+ if( bWithNum )
+ {
+ XubString aListLabelStr = GetNumString();
+ if ( aListLabelStr.Len() > 0 )
+ {
+ if ( bAddSpaceAfterListLabelStr )
+ {
+ const sal_Unicode aSpace = ' ';
+ aTxt.Insert( aSpace, 0 );
+ }
+ aTxt.Insert( GetNumString(), 0 );
+ }
+ }
+
+ if ( bWithSpacesForLevel && GetActualListLevel() > 0 )
+ {
+ int nLevel( GetActualListLevel() );
+ while ( nLevel > 0 )
+ {
+ const sal_Unicode aSpace = ' ';
+ aTxt.Insert( aSpace , 0 );
+ aTxt.Insert( aSpace , 0 );
+ --nLevel;
+ }
+ }
+
+ return aTxt;
+}
+// <--
+
+BOOL SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx,
+ xub_StrLen nIdx, xub_StrLen nLen, BOOL bWithNum,
+ BOOL bWithFtn, BOOL bReplaceTabsWithSpaces ) const
+{
+ if( &rDestNd == this )
+ return FALSE;
+
+ SwIndex aDestIdx( &rDestNd, rDestNd.GetTxt().Len() );
+ if( pDestIdx )
+ aDestIdx = *pDestIdx;
+ xub_StrLen nDestStt = aDestIdx.GetIndex();
+
+ // Text einfuegen
+ String sTmpText = GetTxt();
+ if( bReplaceTabsWithSpaces )
+ sTmpText.SearchAndReplaceAll('\t', ' ');
+
+ // mask hidden characters
+ const xub_Unicode cChar = CH_TXTATR_BREAKWORD;
+ USHORT nHiddenChrs =
+ SwScriptInfo::MaskHiddenRanges( *this, sTmpText, 0, sTmpText.Len(), cChar );
+
+ sTmpText = sTmpText.Copy( nIdx, nLen );
+ rDestNd.InsertText( sTmpText, aDestIdx );
+ nLen = aDestIdx.GetIndex() - nDestStt;
+
+ // alle FontAttribute mit CHARSET Symbol in dem Bereich setzen
+ if ( HasHints() )
+ {
+ xub_StrLen nInsPos = nDestStt - nIdx;
+ for ( USHORT i = 0; i < m_pSwpHints->Count(); i++ )
+ {
+ const SwTxtAttr* pHt = (*m_pSwpHints)[i];
+ const xub_StrLen nAttrStartIdx = *pHt->GetStart();
+ const USHORT nWhich = pHt->Which();
+ if (nIdx + nLen <= nAttrStartIdx)
+ break; // ueber das Textende
+
+ const xub_StrLen *pEndIdx = pHt->GetEnd();
+ if( pEndIdx && *pEndIdx > nIdx &&
+ ( RES_CHRATR_FONT == nWhich ||
+ RES_TXTATR_CHARFMT == nWhich ||
+ RES_TXTATR_AUTOFMT == nWhich ))
+ {
+ const SvxFontItem* const pFont =
+ static_cast<const SvxFontItem*>(
+ CharFmt::GetItem( *pHt, RES_CHRATR_FONT ));
+ if ( pFont && RTL_TEXTENCODING_SYMBOL == pFont->GetCharSet() )
+ {
+ // attribute in area => copy
+ rDestNd.InsertItem( *const_cast<SvxFontItem*>(pFont),
+ nInsPos + nAttrStartIdx, nInsPos + *pEndIdx );
+ }
+ }
+ else if ( pHt->HasDummyChar() && (nAttrStartIdx >= nIdx) )
+ {
+ aDestIdx = nInsPos + nAttrStartIdx;
+ switch( nWhich )
+ {
+ case RES_TXTATR_FIELD:
+ {
+ const XubString aExpand( ((SwTxtFld*)pHt)->GetFld().GetFld()->Expand() );
+ if( aExpand.Len() )
+ {
+ aDestIdx++; // dahinter einfuegen;
+ rDestNd.InsertText( aExpand, aDestIdx );
+ aDestIdx = nInsPos + nAttrStartIdx;
+ nInsPos = nInsPos + aExpand.Len();
+ }
+ rDestNd.EraseText( aDestIdx, 1 );
+ --nInsPos;
+ }
+ break;
+
+ case RES_TXTATR_FTN:
+ {
+ if ( bWithFtn )
+ {
+ const SwFmtFtn& rFtn = pHt->GetFtn();
+ XubString sExpand;
+ if( rFtn.GetNumStr().Len() )
+ sExpand = rFtn.GetNumStr();
+ else if( rFtn.IsEndNote() )
+ sExpand = GetDoc()->GetEndNoteInfo().aFmt.
+ GetNumStr( rFtn.GetNumber() );
+ else
+ sExpand = GetDoc()->GetFtnInfo().aFmt.
+ GetNumStr( rFtn.GetNumber() );
+ if( sExpand.Len() )
+ {
+ aDestIdx++; // insert behind
+ SvxEscapementItem aItem(
+ SVX_ESCAPEMENT_SUPERSCRIPT );
+ rDestNd.InsertItem(aItem,
+ aDestIdx.GetIndex(),
+ aDestIdx.GetIndex() );
+ rDestNd.InsertText( sExpand, aDestIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND);
+ aDestIdx = nInsPos + nAttrStartIdx;
+ nInsPos = nInsPos + sExpand.Len();
+ }
+ }
+ rDestNd.EraseText( aDestIdx, 1 );
+ --nInsPos;
+ }
+ break;
+
+ default:
+ rDestNd.EraseText( aDestIdx, 1 );
+ --nInsPos;
+ }
+ }
+ }
+ }
+
+ if( bWithNum )
+ {
+ aDestIdx = nDestStt;
+ rDestNd.InsertText( GetNumString(), aDestIdx );
+ }
+
+ if ( nHiddenChrs > 0 )
+ {
+ aDestIdx = 0;
+ while ( aDestIdx < rDestNd.GetTxt().Len() )
+ {
+ if ( cChar == rDestNd.GetTxt().GetChar( aDestIdx.GetIndex() ) )
+ {
+ xub_StrLen nIndex = aDestIdx.GetIndex();
+ while ( nIndex < rDestNd.GetTxt().Len() &&
+ cChar == rDestNd.GetTxt().GetChar( ++nIndex ) )
+ ;
+ rDestNd.EraseText( aDestIdx, nIndex - aDestIdx.GetIndex() );
+ }
+ else
+ ++aDestIdx;
+ }
+ }
+
+ return TRUE;
+}
+
+const ModelToViewHelper::ConversionMap*
+ SwTxtNode::BuildConversionMap( rtl::OUString& rRetText ) const
+{
+ const rtl::OUString& rNodeText = GetTxt();
+ rRetText = rNodeText;
+ ModelToViewHelper::ConversionMap* pConversionMap = 0;
+
+ const SwpHints* pSwpHints2 = GetpSwpHints();
+ xub_StrLen nPos = 0;
+
+ for ( USHORT i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i )
+ {
+ const SwTxtAttr* pAttr = (*pSwpHints2)[i];
+ if ( RES_TXTATR_FIELD == pAttr->Which() )
+ {
+ const XubString aExpand( ((SwTxtFld*)pAttr)->GetFld().GetFld()->Expand() );
+ if ( aExpand.Len() > 0 )
+ {
+ const xub_StrLen nFieldPos = *pAttr->GetStart();
+ rRetText = rRetText.replaceAt( nPos + nFieldPos, 1, aExpand );
+ if ( !pConversionMap )
+ pConversionMap = new ModelToViewHelper::ConversionMap;
+ pConversionMap->push_back(
+ ModelToViewHelper::ConversionMapEntry(
+ nFieldPos, nPos + nFieldPos ) );
+ nPos += ( aExpand.Len() - 1 );
+ }
+ }
+ }
+
+ if ( pConversionMap && pConversionMap->size() )
+ pConversionMap->push_back(
+ ModelToViewHelper::ConversionMapEntry(
+ rNodeText.getLength()+1, rRetText.getLength()+1 ) );
+
+ return pConversionMap;
+}
+
+XubString SwTxtNode::GetRedlineTxt( xub_StrLen nIdx, xub_StrLen nLen,
+ BOOL bExpandFlds, BOOL bWithNum ) const
+{
+ SvUShorts aRedlArr;
+ const SwDoc* pDoc = GetDoc();
+ USHORT nRedlPos = pDoc->GetRedlinePos( *this, nsRedlineType_t::REDLINE_DELETE );
+ if( USHRT_MAX != nRedlPos )
+ {
+ // es existiert fuer den Node irgendein Redline-Delete-Object
+ const ULONG nNdIdx = GetIndex();
+ for( ; nRedlPos < pDoc->GetRedlineTbl().Count() ; ++nRedlPos )
+ {
+ const SwRedline* pTmp = pDoc->GetRedlineTbl()[ nRedlPos ];
+ if( nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
+ {
+ const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
+ if( pRStt->nNode < nNdIdx )
+ {
+ if( pREnd->nNode > nNdIdx )
+ // Absatz ist komplett geloescht
+ return aEmptyStr;
+ else if( pREnd->nNode == nNdIdx )
+ {
+ // von 0 bis nContent ist alles geloescht
+ aRedlArr.Insert( xub_StrLen(0), aRedlArr.Count() );
+ aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() );
+ }
+ }
+ else if( pRStt->nNode == nNdIdx )
+ {
+ aRedlArr.Insert( pRStt->nContent.GetIndex(), aRedlArr.Count() );
+ if( pREnd->nNode == nNdIdx )
+ aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() );
+ else
+ {
+ aRedlArr.Insert( GetTxt().Len(), aRedlArr.Count() );
+ break; // mehr kann nicht kommen
+ }
+ }
+ else
+ break; // mehr kann nicht kommen
+ }
+ }
+ }
+
+ XubString aTxt( GetTxt().Copy( nIdx, nLen ) );
+
+ xub_StrLen nTxtStt = nIdx, nIdxEnd = nIdx + aTxt.Len();
+ for( USHORT n = 0; n < aRedlArr.Count(); n += 2 )
+ {
+ xub_StrLen nStt = aRedlArr[ n ], nEnd = aRedlArr[ n+1 ];
+ if( ( nIdx <= nStt && nStt <= nIdxEnd ) ||
+ ( nIdx <= nEnd && nEnd <= nIdxEnd ))
+ {
+ if( nStt < nIdx ) nStt = nIdx;
+ if( nIdxEnd < nEnd ) nEnd = nIdxEnd;
+ xub_StrLen nDelCnt = nEnd - nStt;
+ aTxt.Erase( nStt - nTxtStt, nDelCnt );
+ Replace0xFF( aTxt, nTxtStt, nStt - nTxtStt, bExpandFlds );
+ nTxtStt = nTxtStt + nDelCnt;
+ }
+ else if( nStt >= nIdxEnd )
+ break;
+ }
+ Replace0xFF( aTxt, nTxtStt, aTxt.Len(), bExpandFlds );
+
+ if( bWithNum )
+ aTxt.Insert( GetNumString(), 0 );
+ return aTxt;
+}
+
+/*************************************************************************
+ * SwTxtNode::ReplaceText
+ *************************************************************************/
+
+void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen,
+ const XubString& rText )
+{
+ ASSERT( rStart.GetIndex() < m_Text.Len() &&
+ rStart.GetIndex() + nDelLen <= m_Text.Len(),
+ "SwTxtNode::ReplaceText: index out of bounds" );
+ const xub_StrLen nStartPos = rStart.GetIndex();
+ xub_StrLen nEndPos = nStartPos + nDelLen;
+ xub_StrLen nLen = nDelLen;
+ for ( xub_StrLen nPos = nStartPos; nPos < nEndPos; ++nPos )
+ {
+ if ( ( CH_TXTATR_BREAKWORD == m_Text.GetChar( nPos ) ) ||
+ ( CH_TXTATR_INWORD == m_Text.GetChar( nPos ) ) )
+ {
+ SwTxtAttr *const pHint = GetTxtAttrForCharAt( nPos );
+ if (pHint)
+ {
+ ASSERT (!( pHint->GetEnd() && pHint->HasDummyChar()
+ && (*pHint->GetStart() < nEndPos)
+ && (*pHint->GetEnd() > nEndPos) ),
+ "ReplaceText: ERROR: "
+ "deleting left-overlapped attribute with CH_TXTATR");
+ DeleteAttribute( pHint );
+ --nEndPos;
+ --nLen;
+ }
+ }
+ }
+
+ BOOL bOldExpFlg = IsIgnoreDontExpand();
+ SetIgnoreDontExpand( TRUE );
+
+ if( nLen && rText.Len() )
+ {
+ // dann das 1. Zeichen ersetzen den Rest loschen und einfuegen
+ // Dadurch wird die Attributierung des 1. Zeichen expandiert!
+ m_Text.SetChar( nStartPos, rText.GetChar( 0 ) );
+
+ ((SwIndex&)rStart)++;
+ m_Text.Erase( rStart.GetIndex(), nLen - 1 );
+ Update( rStart, nLen - 1, true );
+
+ XubString aTmpTxt( rText ); aTmpTxt.Erase( 0, 1 );
+ m_Text.Insert( aTmpTxt, rStart.GetIndex() );
+ Update( rStart, aTmpTxt.Len(), false );
+ }
+ else
+ {
+ m_Text.Erase( nStartPos, nLen );
+ Update( rStart, nLen, true );
+
+ m_Text.Insert( rText, nStartPos );
+ Update( rStart, rText.Len(), false );
+ }
+
+ SetIgnoreDontExpand( bOldExpFlg );
+ SwDelTxt aDelHint( nStartPos, nDelLen );
+ SwModify::Modify( 0, &aDelHint );
+
+ SwInsTxt aHint( nStartPos, rText.Len() );
+ SwModify::Modify( 0, &aHint );
+}
+
+// --> OD 2008-03-27 #refactorlists#
+namespace {
+ // Helper method for special handling of modified attributes at text node.
+ // The following is handled:
+ // (1) on changing the paragraph style - RES_FMT_CHG:
+ // Check, if list style of the text node is changed. If yes, add respectively
+ // remove the text node to the corresponding list.
+ // (2) on changing the attributes - RES_ATTRSET_CHG:
+ // Same as (1).
+ // (3) on changing the list style - RES_PARATR_NUMRULE:
+ // Same as (1).
+ void HandleModifyAtTxtNode( SwTxtNode& rTxtNode,
+ const SfxPoolItem* pOldValue,
+ const SfxPoolItem* pNewValue )
+ {
+ const USHORT nWhich = pOldValue ? pOldValue->Which() :
+ pNewValue ? pNewValue->Which() : 0 ;
+ bool bNumRuleSet = false;
+ bool bParagraphStyleChanged = false;
+ String sNumRule;
+ String sOldNumRule;
+ switch ( nWhich )
+ {
+ case RES_FMT_CHG:
+ {
+ bParagraphStyleChanged = true;
+ if( rTxtNode.GetNodes().IsDocNodes() )
+ {
+ // --> OD 2008-12-17 #i70748#
+ // The former list style set at the paragraph can not be
+ // retrieved from the change set.
+// sOldNumRule =
+// dynamic_cast<const SwFmtChg*>(pOldValue)->pChangedFmt->GetNumRule().GetValue();
+ const SwNumRule* pFormerNumRuleAtTxtNode =
+ rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
+ if ( pFormerNumRuleAtTxtNode )
+ {
+ sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
+ }
+ // <--
+ // --> OD 2008-11-19 #i70748#
+ if ( rTxtNode.IsEmptyListStyleDueToSetOutlineLevelAttr() )
+ {
+ const SwNumRuleItem& rNumRuleItem = rTxtNode.GetTxtColl()->GetNumRule();
+ if ( rNumRuleItem.GetValue().Len() > 0 )
+ {
+ rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ }
+ }
+ // <--
+ const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
+ if ( pNumRuleAtTxtNode )
+ {
+ bNumRuleSet = true;
+ sNumRule = pNumRuleAtTxtNode->GetName();
+ }
+ }
+ break;
+ }
+ case RES_ATTRSET_CHG:
+ {
+ const SfxPoolItem* pItem = 0;
+ // --> OD 2008-12-19 #i70748#
+ // The former list style set at the paragraph can not be
+ // retrieved from the change set.
+// if ( dynamic_cast<const SwAttrSetChg*>(pOldValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, FALSE, &pItem ) ==
+// SFX_ITEM_SET )
+// {
+// sOldNumRule = dynamic_cast<const SwNumRuleItem*>(pItem)->GetValue();
+// }
+ const SwNumRule* pFormerNumRuleAtTxtNode =
+ rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
+ if ( pFormerNumRuleAtTxtNode )
+ {
+ sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
+ }
+ // <--
+ if ( dynamic_cast<const SwAttrSetChg*>(pNewValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, FALSE, &pItem ) ==
+ SFX_ITEM_SET )
+ {
+ // --> OD 2008-11-19 #i70748#
+ rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ // <--
+ bNumRuleSet = true;
+ // The new list style set at the paragraph can not be
+ // retrieved from the change set.
+// sNumRule = dynamic_cast<const SwNumRuleItem*>(pItem)->GetValue();
+ // <--
+ }
+ // --> OD 2008-12-17 #i70748#
+ // The new list style set at the paragraph.
+ const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
+ if ( pNumRuleAtTxtNode )
+ {
+ sNumRule = pNumRuleAtTxtNode->GetName();
+ }
+ // <--
+ break;
+ }
+ case RES_PARATR_NUMRULE:
+ {
+ if ( rTxtNode.GetNodes().IsDocNodes() )
+ {
+ // The former list style set at the paragraph can not be
+ // retrieved from the change set.
+// if ( pOldValue )
+// {
+// sOldNumRule = dynamic_cast<const SwNumRuleItem*>(pOldValue)->GetValue();
+// }
+ const SwNumRule* pFormerNumRuleAtTxtNode =
+ rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
+ if ( pFormerNumRuleAtTxtNode )
+ {
+ sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
+ }
+ // <--
+ if ( pNewValue )
+ {
+ // --> OD 2008-11-19 #i70748#
+ rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ // <--
+ bNumRuleSet = true;
+ // --> OD 2008-12-17 #i70748#
+ // The new list style set at the paragraph can not be
+ // retrieved from the change set.
+// sNumRule = dynamic_cast<const SwNumRuleItem*>(pNewValue)->GetValue();
+ // <--
+ }
+ // --> OD 2008-12-17 #i70748#
+ // The new list style set at the paragraph.
+ const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
+ if ( pNumRuleAtTxtNode )
+ {
+ sNumRule = pNumRuleAtTxtNode->GetName();
+ }
+ // <--
+ }
+ break;
+ }
+ }
+ if ( sNumRule != sOldNumRule )
+ {
+ if ( bNumRuleSet )
+ {
+ if ( sNumRule.Len() == 0 )
+ {
+ rTxtNode.RemoveFromList();
+ if ( bParagraphStyleChanged )
+ {
+ SvUShortsSort aResetAttrsArray;
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
+ SwPaM aPam( rTxtNode );
+ // --> OD 2008-11-28 #i96644#
+ // suppress side effect "send data changed events"
+ rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False,
+ &aResetAttrsArray,
+ false );
+ // <--
+ }
+ }
+ else
+ {
+ rTxtNode.RemoveFromList();
+ // If new list style is the outline style, apply outline
+ // level as the list level.
+ if ( sNumRule ==
+ String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) )
+ {
+ // --> OD 2008-09-10 #i70748#
+ ASSERT( rTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle(),
+ "<HandleModifyAtTxtNode()> - text node with outline style, but its paragraph style is not assigned to outline style." );
+ int nNewListLevel =
+ rTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
+ // <--
+ if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
+ {
+ rTxtNode.SetAttrListLevel( nNewListLevel );
+ }
+ }
+ rTxtNode.AddToList();
+ }
+ }
+ else // <sNumRule.Len() == 0 && sOldNumRule.Len() != 0>
+ {
+ rTxtNode.RemoveFromList();
+ if ( bParagraphStyleChanged )
+ {
+ SvUShortsSort aResetAttrsArray;
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
+ SwPaM aPam( rTxtNode );
+ // --> OD 2008-11-28 #i96644#
+ // suppress side effect "send data changed events"
+ rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False,
+ &aResetAttrsArray,
+ false );
+ // <--
+ // --> OD 2008-11-19 #i70748#
+ if ( dynamic_cast<const SfxUInt16Item &>(rTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, FALSE )).GetValue() > 0 )
+ {
+ rTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
+ }
+ // <--
+ }
+ }
+ }
+ else if ( sNumRule.Len() > 0 && !rTxtNode.IsInList() )
+ {
+ rTxtNode.AddToList();
+ }
+ // <--
+ }
+ // End of method <HandleModifyAtTxtNode>
+}
+// <--
+
+void SwTxtNode::Modify( SfxPoolItem* pOldValue, SfxPoolItem* pNewValue )
+{
+ bool bWasNotifiable = m_bNotifiable;
+ m_bNotifiable = false;
+
+ // Bug 24616/24617:
+ // Modify ueberladen, damit beim Loeschen von Vorlagen diese
+ // wieder richtig verwaltet werden (Outline-Numerierung!!)
+ // Bug25481:
+ // bei Nodes im Undo nie _ChgTxtCollUpdateNum rufen.
+ if( pOldValue && pNewValue && RES_FMT_CHG == pOldValue->Which() &&
+ pRegisteredIn == ((SwFmtChg*)pNewValue)->pChangedFmt &&
+ GetNodes().IsDocNodes() )
+ {
+ _ChgTxtCollUpdateNum(
+ (SwTxtFmtColl*)((SwFmtChg*)pOldValue)->pChangedFmt,
+ (SwTxtFmtColl*)((SwFmtChg*)pNewValue)->pChangedFmt );
+ }
+
+ // --> OD 2008-03-27 #refactorlists#
+ if ( !mbInSetOrResetAttr )
+ {
+ HandleModifyAtTxtNode( *this, pOldValue, pNewValue );
+ }
+ // <--
+
+ SwCntntNode::Modify( pOldValue, pNewValue );
+
+ SwDoc * pDoc = GetDoc();
+ // --> OD 2005-11-02 #125329# - assure that text node is in document nodes array
+ if ( pDoc && !pDoc->IsInDtor() && &pDoc->GetNodes() == &GetNodes() )
+ // <--
+ {
+ pDoc->GetNodes().UpdateOutlineNode(*this);
+ }
+
+ m_bNotifiable = bWasNotifiable;
+
+ if (pOldValue && (RES_REMOVE_UNO_OBJECT == pOldValue->Which()))
+ { // invalidate cached uno object
+ SetXParagraph(::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextContent>(0));
+ }
+}
+
+SwFmtColl* SwTxtNode::ChgFmtColl( SwFmtColl *pNewColl )
+{
+ ASSERT( pNewColl,"ChgFmtColl: Collectionpointer ist 0." );
+ ASSERT( HAS_BASE( SwTxtFmtColl, pNewColl ),
+ "ChgFmtColl: ist kein Text-Collectionpointer." );
+
+ SwTxtFmtColl *pOldColl = GetTxtColl();
+ if( pNewColl != pOldColl )
+ {
+ SetCalcHiddenCharFlags();
+ SwCntntNode::ChgFmtColl( pNewColl );
+ // --> OD 2008-03-27 #refactorlists#
+// NumRuleChgd();
+#if OSL_DEBUG_LEVEL > 1
+ ASSERT( !mbInSetOrResetAttr,
+ "DEBUG ASSERTION - <SwTxtNode::ChgFmtColl(..)> called during <Set/ResetAttr(..)>" )
+#endif
+ if ( !mbInSetOrResetAttr )
+ {
+ SwFmtChg aTmp1( pOldColl );
+ SwFmtChg aTmp2( pNewColl );
+ HandleModifyAtTxtNode( *this, &aTmp1, &aTmp2 );
+ }
+ // <--
+ }
+
+ // nur wenn im normalen Nodes-Array
+ if( GetNodes().IsDocNodes() )
+ {
+ _ChgTxtCollUpdateNum( pOldColl, static_cast<SwTxtFmtColl *>(pNewColl) );
+ }
+
+ GetNodes().UpdateOutlineNode(*this);
+
+ return pOldColl;
+}
+
+SwNodeNum* SwTxtNode::CreateNum() const
+{
+ if ( !mpNodeNum )
+ {
+ // --> OD 2008-02-19 #refactorlists#
+ mpNodeNum = new SwNodeNum( const_cast<SwTxtNode*>(this) );
+ // <--
+ }
+ return mpNodeNum;
+}
+
+SwNumberTree::tNumberVector SwTxtNode::GetNumberVector() const
+{
+ if ( GetNum() )
+ {
+ return GetNum()->GetNumberVector();
+ }
+ else
+ {
+ SwNumberTree::tNumberVector aResult;
+ return aResult;
+ }
+}
+
+bool SwTxtNode::IsOutline() const
+{
+ bool bResult = false;
+
+ //if ( GetOutlineLevel() != NO_NUMBERING )//#outline level,removed by zhaojianwei
+ if ( GetAttrOutlineLevel() > 0 ) //<-end,zhaojianwei
+ {
+ bResult = !IsInRedlines();
+ }
+ else
+ {
+ const SwNumRule* pRule( GetNum() ? GetNum()->GetNumRule() : 0L );
+ if ( pRule && pRule->IsOutlineRule() )
+ {
+ bResult = !IsInRedlines();
+ }
+ }
+
+ return bResult;
+}
+
+bool SwTxtNode::IsOutlineStateChanged() const
+{
+ return IsOutline() != m_bLastOutlineState;
+}
+
+void SwTxtNode::UpdateOutlineState()
+{
+ m_bLastOutlineState = IsOutline();
+}
+
+//#outline level, zhaojianwei
+int SwTxtNode::GetAttrOutlineLevel() const
+{
+ return ((const SfxUInt16Item &)GetAttr(RES_PARATR_OUTLINELEVEL)).GetValue();
+}
+void SwTxtNode::SetAttrOutlineLevel(int nLevel)
+{
+ ASSERT( 0 <= nLevel && nLevel <= MAXLEVEL ,"SwTxtNode: Level Out Of Range" );//#outline level,zhaojianwei
+ if ( 0 <= nLevel && nLevel <= MAXLEVEL )
+ {
+ SetAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL,
+ static_cast<UINT16>(nLevel) ) );
+ }
+}
+//<-end
+
+// --> OD 2008-11-19 #i70748#
+bool SwTxtNode::IsEmptyListStyleDueToSetOutlineLevelAttr()
+{
+ return mbEmptyListStyleSetDueToSetOutlineLevelAttr;
+}
+
+void SwTxtNode::SetEmptyListStyleDueToSetOutlineLevelAttr()
+{
+ if ( !mbEmptyListStyleSetDueToSetOutlineLevelAttr )
+ {
+ SetAttr( SwNumRuleItem() );
+ mbEmptyListStyleSetDueToSetOutlineLevelAttr = true;
+ }
+}
+
+void SwTxtNode::ResetEmptyListStyleDueToResetOutlineLevelAttr()
+{
+ if ( mbEmptyListStyleSetDueToSetOutlineLevelAttr )
+ {
+ ResetAttr( RES_PARATR_NUMRULE );
+ mbEmptyListStyleSetDueToSetOutlineLevelAttr = false;
+ }
+}
+// <--
+
+
+// --> OD 2008-02-27 #refactorlists#
+void SwTxtNode::SetAttrListLevel( int nLevel )
+{
+ if ( nLevel < 0 || nLevel >= MAXLEVEL )
+ {
+ ASSERT( false,
+ "<SwTxtNode::SetAttrListLevel()> - value of parameter <nLevel> is out of valid range" );
+ return;
+ }
+
+ SfxInt16Item aNewListLevelItem( RES_PARATR_LIST_LEVEL,
+ static_cast<INT16>(nLevel) );
+ SetAttr( aNewListLevelItem );
+}
+// <--
+// --> OD 2008-02-27 #refactorlists#
+bool SwTxtNode::HasAttrListLevel() const
+{
+ return GetpSwAttrSet() &&
+ GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_LEVEL, FALSE ) == SFX_ITEM_SET;
+}
+// <--
+// --> OD 2008-02-27 #refactorlists#
+int SwTxtNode::GetAttrListLevel() const
+{
+ int nAttrListLevel = 0;
+
+ const SfxInt16Item& aListLevelItem =
+ dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_LEVEL ));
+ nAttrListLevel = static_cast<int>(aListLevelItem.GetValue());
+
+ return nAttrListLevel;
+}
+// <--
+
+int SwTxtNode::GetActualListLevel() const
+{
+ return GetNum() ? GetNum()->GetLevelInListTree() : -1;
+}
+
+// --> OD 2008-02-25 #refactorlists#
+void SwTxtNode::SetListRestart( bool bRestart )
+{
+// CreateNum()->SetRestart(bRestart);
+ if ( !bRestart )
+ {
+ // attribute not contained in paragraph style's attribute set. Thus,
+ // it can be reset to the attribute pool default by resetting the attribute.
+ ResetAttr( RES_PARATR_LIST_ISRESTART );
+ }
+ else
+ {
+ SfxBoolItem aNewIsRestartItem( RES_PARATR_LIST_ISRESTART,
+ TRUE );
+ SetAttr( aNewIsRestartItem );
+ }
+}
+
+// --> OD 2008-02-25 #refactorlists#
+bool SwTxtNode::IsListRestart() const
+{
+// return GetNum() ? GetNum()->IsRestart() : false;
+ const SfxBoolItem& aIsRestartItem =
+ dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISRESTART ));
+
+ return aIsRestartItem.GetValue() ? true : false;
+}
+// <--
+
+/** Returns if the paragraph has a visible numbering or bullet.
+ This includes all kinds of numbering/bullet/outlines.
+ OD 2008-02-28 #newlistlevelattrs#
+ The concrete list label string has to be checked, too.
+ */
+bool SwTxtNode::HasVisibleNumberingOrBullet() const
+{
+ bool bRet = false;
+
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule && IsCountedInList())
+ {
+ // --> OD 2008-03-19 #i87154#
+ // Correction of #newlistlevelattrs#:
+ // The numbering type has to be checked for bullet lists.
+ const SwNumFmt& rFmt = pRule->Get( static_cast<USHORT>(GetActualListLevel() ));
+ if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() ||
+ pRule->MakeNumString( *(GetNum()) ).Len() > 0 )
+ {
+ bRet = true;
+ }
+ // <--
+ }
+
+ return bRet;
+}
+
+// --> OD 2008-02-25 #refactorlists#
+void SwTxtNode::SetAttrListRestartValue( SwNumberTree::tSwNumTreeNumber nNumber )
+{
+// CreateNum()->SetStart(nNumber);
+ const bool bChanged( HasAttrListRestartValue()
+ ? GetAttrListRestartValue() != nNumber
+ : nNumber != USHRT_MAX );
+
+ if ( bChanged || !HasAttrListRestartValue() )
+ {
+ if ( nNumber == USHRT_MAX )
+ {
+ ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
+ }
+ else
+ {
+ SfxInt16Item aNewListRestartValueItem( RES_PARATR_LIST_RESTARTVALUE,
+ static_cast<INT16>(nNumber) );
+ SetAttr( aNewListRestartValueItem );
+ }
+ }
+}
+// <--
+
+// --> OD 2008-02-27 #refactorlists#
+bool SwTxtNode::HasAttrListRestartValue() const
+{
+ return GetpSwAttrSet() &&
+ GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_RESTARTVALUE, FALSE ) == SFX_ITEM_SET;
+}
+// <--
+SwNumberTree::tSwNumTreeNumber SwTxtNode::GetAttrListRestartValue() const
+{
+ ASSERT( HasAttrListRestartValue(),
+ "<SwTxtNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." );
+
+ const SfxInt16Item& aListRestartValueItem =
+ dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_RESTARTVALUE ));
+ return static_cast<SwNumberTree::tSwNumTreeNumber>(aListRestartValueItem.GetValue());
+}
+
+// --> OD 2008-02-25 #refactorlists#
+SwNumberTree::tSwNumTreeNumber SwTxtNode::GetActualListStartValue() const
+{
+// return GetNum() ? GetNum()->GetStart() : 1;
+ SwNumberTree::tSwNumTreeNumber nListRestartValue = 1;
+
+ if ( IsListRestart() && HasAttrListRestartValue() )
+ {
+ nListRestartValue = GetAttrListRestartValue();
+ }
+ else
+ {
+ SwNumRule* pRule = GetNumRule();
+ if ( pRule )
+ {
+ const SwNumFmt* pFmt =
+ pRule->GetNumFmt( static_cast<USHORT>(GetAttrListLevel()) );
+ if ( pFmt )
+ {
+ nListRestartValue = pFmt->GetStart();
+ }
+ }
+ }
+
+ return nListRestartValue;
+}
+// <--
+
+bool SwTxtNode::IsNotifiable() const
+{
+ return m_bNotifiable && IsNotificationEnabled();
+}
+
+bool SwTxtNode::IsNotificationEnabled() const
+{
+ bool bResult = false;
+ const SwDoc * pDoc = GetDoc();
+ if( pDoc )
+ {
+ bResult = pDoc->IsInReading() || pDoc->IsInDtor() ? false : true;
+ }
+ return bResult;
+}
+
+// --> OD 2008-02-27 #refactorlists#
+void SwTxtNode::SetCountedInList( bool bCounted )
+{
+ if ( bCounted )
+ {
+ // attribute not contained in paragraph style's attribute set. Thus,
+ // it can be reset to the attribute pool default by resetting the attribute.
+ ResetAttr( RES_PARATR_LIST_ISCOUNTED );
+ }
+ else
+ {
+ SfxBoolItem aIsCountedInListItem( RES_PARATR_LIST_ISCOUNTED, FALSE );
+ SetAttr( aIsCountedInListItem );
+ }
+}
+// <--
+
+bool SwTxtNode::IsCountedInList() const
+{
+ const SfxBoolItem& aIsCountedInListItem =
+ dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISCOUNTED ));
+
+ return aIsCountedInListItem.GetValue() ? true : false;
+}
+
+// --> OD 2008-03-13 #refactorlists#
+void SwTxtNode::AddToList()
+{
+ if ( IsInList() )
+ {
+ ASSERT( false,
+ "<SwTxtNode::AddToList()> - the text node is already added to a list. Serious defect -> please inform OD" );
+ return;
+ }
+
+ const String sListId = GetListId();
+ if ( sListId.Len() > 0 )
+ {
+ SwList* pList = GetDoc()->getListByName( sListId );
+ if ( pList == 0 )
+ {
+ // Create corresponding list.
+ SwNumRule* pNumRule = GetNumRule();
+ if ( pNumRule )
+ {
+ pList = GetDoc()->createList( sListId, GetNumRule()->GetName() );
+ }
+ }
+ ASSERT( pList != 0,
+ "<SwTxtNode::AddToList()> - no list for given list id. Serious defect -> please inform OD" );
+ if ( pList )
+ {
+ pList->InsertListItem( *CreateNum(), GetAttrListLevel() );
+ mpList = pList;
+ }
+ }
+}
+
+void SwTxtNode::RemoveFromList()
+{
+ if ( IsInList() )
+ {
+ mpList->RemoveListItem( *mpNodeNum );
+ mpList = 0;
+ delete mpNodeNum;
+ mpNodeNum = 0L;
+ }
+}
+
+bool SwTxtNode::IsInList() const
+{
+ return GetNum() != 0 && GetNum()->GetParent() != 0;
+}
+// <--
+
+bool SwTxtNode::IsFirstOfNumRule() const
+{
+ bool bResult = false;
+
+ if ( GetNum() && GetNum()->GetNumRule())
+ bResult = GetNum()->IsFirst();
+
+ return bResult;
+}
+
+// --> OD 2008-02-20 #refactorlists#
+void SwTxtNode::SetListId( const String sListId )
+{
+ const SfxStringItem& rListIdItem =
+ dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
+ if ( rListIdItem.GetValue() != sListId )
+ {
+ if ( sListId.Len() == 0 )
+ {
+ ResetAttr( RES_PARATR_LIST_ID );
+ }
+ else
+ {
+ SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId );
+ SetAttr( aNewListIdItem );
+ }
+ }
+}
+
+String SwTxtNode::GetListId() const
+{
+ String sListId;
+
+ const SfxStringItem& rListIdItem =
+ dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
+ sListId = rListIdItem.GetValue();
+
+ // As long as no explicit list id attribute is set, use the list id of
+ // the list, which has been created for the applied list style.
+ if ( sListId.Len() == 0 )
+ {
+ SwNumRule* pRule = GetNumRule();
+ if ( pRule )
+ {
+ sListId = pRule->GetDefaultListId();
+//#if OSL_DEBUG_LEVEL > 1
+// ASSERT( false,
+// "DEBUG ASSERTION: default list id of list style is applied." );
+//#endif
+// // setting list id directly using <SwCntntNode::SetAttr(..)>,
+// // because no handling of this attribute set is needed and to avoid
+// // recursive calls of <SwTxtNode::SetAttr(..)>
+// SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId );
+// const_cast<SwTxtNode*>(this)->SwCntntNode::SetAttr( aNewListIdItem );
+ }
+ }
+
+ return sListId;
+}
+// <--
+
+/** Determines, if the list level indent attributes can be applied to the
+ paragraph.
+
+ OD 2008-01-17 #newlistlevelattrs#
+ The list level indents can be applied to the paragraph under the one
+ of following conditions:
+ - the list style is directly applied to the paragraph and the paragraph
+ has no own indent attributes.
+ - the list style is applied to the paragraph through one of its paragraph
+ styles, the paragraph has no own indent attributes and on the paragraph
+ style hierarchy from the paragraph to the paragraph style with the
+ list style no indent attributes are found.
+
+ @author OD
+
+ @return boolean
+*/
+bool SwTxtNode::AreListLevelIndentsApplicable() const
+{
+ bool bAreListLevelIndentsApplicable( true );
+
+ if ( !GetNum() || !GetNum()->GetNumRule() )
+ {
+ // no list style applied to paragraph
+ bAreListLevelIndentsApplicable = false;
+ }
+ else if ( HasSwAttrSet() &&
+ GetpSwAttrSet()->GetItemState( RES_LR_SPACE, FALSE ) == SFX_ITEM_SET )
+ {
+ // paragraph has hard-set indent attributes
+ bAreListLevelIndentsApplicable = false;
+ }
+ else if ( HasSwAttrSet() &&
+ GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, FALSE ) == SFX_ITEM_SET )
+ {
+ // list style is directly applied to paragraph and paragraph has no
+ // hard-set indent attributes
+ bAreListLevelIndentsApplicable = true;
+ }
+ else
+ {
+ // list style is applied through one of the paragraph styles and
+ // paragraph has no hard-set indent attributes
+
+ // check, paragraph's
+ const SwTxtFmtColl* pColl = GetTxtColl();
+ while ( pColl )
+ {
+ if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, FALSE ) == SFX_ITEM_SET )
+ {
+ // indent attributes found in the paragraph style hierarchy.
+ bAreListLevelIndentsApplicable = false;
+ break;
+ }
+
+ if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, FALSE ) == SFX_ITEM_SET )
+ {
+ // paragraph style with the list style found and until now no
+ // indent attributes are found in the paragraph style hierarchy.
+ bAreListLevelIndentsApplicable = true;
+ break;
+ }
+
+ pColl = dynamic_cast<const SwTxtFmtColl*>(pColl->DerivedFrom());
+ ASSERT( pColl,
+ "<SwTxtNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." );
+ }
+ }
+
+ return bAreListLevelIndentsApplicable;
+}
+
+/** Retrieves the list tab stop position, if the paragraph's list level defines
+ one and this list tab stop has to merged into the tap stops of the paragraph
+
+ OD 2008-01-17 #newlistlevelattrs#
+
+ @author OD
+
+ @param nListTabStopPosition
+ output parameter - containing the list tab stop position
+
+ @return boolean - indicating, if a list tab stop position is provided
+*/
+bool SwTxtNode::GetListTabStopPosition( long& nListTabStopPosition ) const
+{
+ bool bListTanStopPositionProvided( false );
+
+ const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
+ if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
+ {
+ const SwNumFmt& rFmt = pNumRule->Get( static_cast<USHORT>(GetActualListLevel()) );
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT &&
+ rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
+ {
+ bListTanStopPositionProvided = true;
+ nListTabStopPosition = rFmt.GetListtabPos();
+
+ if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
+ {
+ // tab stop position are treated to be relative to the "before text"
+ // indent value of the paragraph. Thus, adjust <nListTabStopPos>.
+ if ( AreListLevelIndentsApplicable() )
+ {
+ nListTabStopPosition -= rFmt.GetIndentAt();
+ }
+ else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
+ {
+ SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
+ nListTabStopPosition -= aItem.GetTxtLeft();
+ }
+ }
+ }
+ }
+
+ return bListTanStopPositionProvided;
+}
+
+/** Retrieves the character following the list label, if the paragraph's
+ list level defines one.
+
+ OD 2008-01-17 #newlistlevelattrs#
+
+ @author OD
+
+ @return XubString - the list tab stop position
+*/
+XubString SwTxtNode::GetLabelFollowedBy() const
+{
+ XubString aLabelFollowedBy;
+
+ const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
+ if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
+ {
+ const SwNumFmt& rFmt = pNumRule->Get( static_cast<USHORT>(GetActualListLevel()) );
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ switch ( rFmt.GetLabelFollowedBy() )
+ {
+ case SvxNumberFormat::LISTTAB:
+ {
+ const sal_Unicode aTab = '\t';
+ aLabelFollowedBy.Insert( aTab, 0 );
+ }
+ break;
+ case SvxNumberFormat::SPACE:
+ {
+ const sal_Unicode aSpace = ' ';
+ aLabelFollowedBy.Insert( aSpace, 0 );
+ }
+ break;
+ case SvxNumberFormat::NOTHING:
+ {
+ // intentionally left blank.
+ }
+ break;
+ default:
+ {
+ ASSERT( false,
+ "<SwTxtNode::GetLabelFollowedBy()> - unknown SvxNumberFormat::GetLabelFollowedBy() return value" );
+ }
+ }
+ }
+ }
+
+ return aLabelFollowedBy;
+}
+
+void SwTxtNode::CalcHiddenCharFlags() const
+{
+ xub_StrLen nStartPos;
+ xub_StrLen nEndPos;
+ // Update of the flags is done inside GetBoundsOfHiddenRange()
+ SwScriptInfo::GetBoundsOfHiddenRange( *this, 0, nStartPos, nEndPos );
+}
+
+// --> FME 2004-06-08 #i12836# enhanced pdf export
+bool SwTxtNode::IsHidden() const
+{
+ if ( HasHiddenParaField() || HasHiddenCharAttribute( true ) )
+ return true;
+
+ const SwSectionNode* pSectNd = FindSectionNode();
+ if ( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
+ return true;
+
+ return false;
+}
+// <--
+
+// --> OD 2008-03-13 #refactorlists#
+namespace {
+ // Helper class for special handling of setting attributes at text node:
+ // In constructor an instance of the helper class recognize whose attributes
+ // are set and perform corresponding actions before the intrinsic set of
+ // attributes has been taken place.
+ // In the destructor - after the attributes have been set at the text
+ // node - corresponding actions are performed.
+ // The following is handled:
+ // (1) When the list style attribute - RES_PARATR_NUMRULE - is set,
+ // (A) list style attribute is empty -> the text node is removed from
+ // its list.
+ // (B) list style attribute is not empty
+ // (a) text node has no list style -> add text node to its list after
+ // the attributes have been set.
+ // (b) text node has list style -> change of list style is notified
+ // after the attributes have been set.
+ // (2) When the list id attribute - RES_PARATR_LIST_ID - is set and changed,
+ // the text node is removed from its current list before the attributes
+ // are set and added to its new list after the attributes have been set.
+ // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is set
+ // and changed after the attributes have been set
+ // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is set
+ // and changed after the attributes have been set
+ // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE -
+ // is set and changed after the attributes have been set
+ // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is set
+ // and changed after the attributes have been set
+ // (7) Set or Reset emtpy list style due to changed outline level - RES_PARATR_OUTLINELEVEL.
+ class HandleSetAttrAtTxtNode
+ {
+ public:
+ HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SfxPoolItem& pItem );
+ HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SfxItemSet& rItemSet );
+ ~HandleSetAttrAtTxtNode();
+
+ private:
+ SwTxtNode& mrTxtNode;
+ bool mbAddTxtNodeToList;
+ bool mbUpdateListLevel;
+ bool mbUpdateListRestart;
+ bool mbUpdateListCount;
+ // --> OD 2008-11-19 #i70748#
+ bool mbOutlineLevelSet;
+ // <--
+ };
+
+ HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SfxPoolItem& pItem )
+ : mrTxtNode( rTxtNode ),
+ mbAddTxtNodeToList( false ),
+ mbUpdateListLevel( false ),
+ mbUpdateListRestart( false ),
+ mbUpdateListCount( false ),
+ // --> OD 2008-11-19 #i70748#
+ mbOutlineLevelSet( false )
+ // <--
+ {
+ switch ( pItem.Which() )
+ {
+ // handle RES_PARATR_NUMRULE
+ case RES_PARATR_NUMRULE:
+ {
+ mrTxtNode.RemoveFromList();
+
+ const SwNumRuleItem& pNumRuleItem =
+ dynamic_cast<const SwNumRuleItem&>(pItem);
+ if ( pNumRuleItem.GetValue().Len() > 0 )
+ {
+ mbAddTxtNodeToList = true;
+ }
+ }
+ break;
+
+ // handle RES_PARATR_LIST_ID
+ case RES_PARATR_LIST_ID:
+ {
+ const SfxStringItem& pListIdItem =
+ dynamic_cast<const SfxStringItem&>(pItem);
+ ASSERT( pListIdItem.GetValue().Len() > 0,
+ "<HandleSetAttrAtTxtNode(..)> - empty list id attribute not excepted. Serious defect -> please inform OD." );
+// const SfxStringItem& rListIdItemOfTxtNode =
+// dynamic_cast<const SfxStringItem&>(
+// rTxtNode.GetAttr( RES_PARATR_LIST_ID ));
+// if ( pListIdItem.GetValue() != rListIdItemOfTxtNode.GetValue() )
+ const String sListIdOfTxtNode = rTxtNode.GetListId();
+ if ( pListIdItem.GetValue() != sListIdOfTxtNode )
+ {
+ mbAddTxtNodeToList = true;
+ if ( mrTxtNode.IsInList() )
+ {
+ mrTxtNode.RemoveFromList();
+ }
+ }
+ }
+ break;
+
+ // handle RES_PARATR_LIST_LEVEL
+ case RES_PARATR_LIST_LEVEL:
+ {
+ const SfxInt16Item& aListLevelItem =
+ dynamic_cast<const SfxInt16Item&>(pItem);
+ if ( aListLevelItem.GetValue() != mrTxtNode.GetAttrListLevel() )
+ {
+ mbUpdateListLevel = true;
+ }
+ }
+ break;
+
+ // handle RES_PARATR_LIST_ISRESTART
+ case RES_PARATR_LIST_ISRESTART:
+ {
+ const SfxBoolItem& aListIsRestartItem =
+ dynamic_cast<const SfxBoolItem&>(pItem);
+ if ( aListIsRestartItem.GetValue() !=
+ (mrTxtNode.IsListRestart() ? TRUE : FALSE) )
+ {
+ mbUpdateListRestart = true;
+ }
+ }
+ break;
+
+ // handle RES_PARATR_LIST_RESTARTVALUE
+ case RES_PARATR_LIST_RESTARTVALUE:
+ {
+ const SfxInt16Item& aListRestartValueItem =
+ dynamic_cast<const SfxInt16Item&>(pItem);
+ if ( !mrTxtNode.HasAttrListRestartValue() ||
+ aListRestartValueItem.GetValue() != mrTxtNode.GetAttrListRestartValue() )
+ {
+ mbUpdateListRestart = true;
+ }
+ }
+ break;
+
+ // handle RES_PARATR_LIST_ISCOUNTED
+ case RES_PARATR_LIST_ISCOUNTED:
+ {
+ const SfxBoolItem& aIsCountedInListItem =
+ dynamic_cast<const SfxBoolItem&>(pItem);
+ if ( aIsCountedInListItem.GetValue() !=
+ (mrTxtNode.IsCountedInList() ? TRUE : FALSE) )
+ {
+ mbUpdateListCount = true;
+ }
+ }
+ break;
+
+ // --> OD 2008-11-19 #i70748#
+ // handle RES_PARATR_OUTLINELEVEL
+ case RES_PARATR_OUTLINELEVEL:
+ {
+ const SfxUInt16Item& aOutlineLevelItem =
+ dynamic_cast<const SfxUInt16Item&>(pItem);
+ if ( aOutlineLevelItem.GetValue() != mrTxtNode.GetAttrOutlineLevel() )
+ {
+ mbOutlineLevelSet = true;
+ }
+ }
+ break;
+ // <--
+ }
+
+ }
+
+ HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SfxItemSet& rItemSet )
+ : mrTxtNode( rTxtNode ),
+ mbAddTxtNodeToList( false ),
+ mbUpdateListLevel( false ),
+ mbUpdateListRestart( false ),
+ mbUpdateListCount( false ),
+ // --> OD 2008-11-19 #i70748#
+ mbOutlineLevelSet( false )
+ // <--
+ {
+ const SfxPoolItem* pItem = 0;
+ // handle RES_PARATR_NUMRULE
+ if ( rItemSet.GetItemState( RES_PARATR_NUMRULE, FALSE, &pItem ) == SFX_ITEM_SET )
+ {
+ mrTxtNode.RemoveFromList();
+
+ const SwNumRuleItem* pNumRuleItem =
+ dynamic_cast<const SwNumRuleItem*>(pItem);
+ if ( pNumRuleItem->GetValue().Len() > 0 )
+ {
+ mbAddTxtNodeToList = true;
+ // --> OD 2008-11-19 #i70748#
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ // <--
+ }
+ }
+
+ // handle RES_PARATR_LIST_ID
+ if ( rItemSet.GetItemState( RES_PARATR_LIST_ID, FALSE, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxStringItem* pListIdItem =
+ dynamic_cast<const SfxStringItem*>(pItem);
+// const SfxStringItem& rListIdItemOfTxtNode =
+// dynamic_cast<const SfxStringItem&>(
+// mrTxtNode.GetAttr( RES_PARATR_LIST_ID ));
+// if ( pListIdItem &&
+// pListIdItem->GetValue() != rListIdItemOfTxtNode.GetValue() )
+ const String sListIdOfTxtNode = mrTxtNode.GetListId();
+ if ( pListIdItem &&
+ pListIdItem->GetValue() != sListIdOfTxtNode )
+ {
+ mbAddTxtNodeToList = true;
+ if ( mrTxtNode.IsInList() )
+ {
+ mrTxtNode.RemoveFromList();
+ }
+ }
+ }
+
+ // handle RES_PARATR_LIST_LEVEL
+ if ( rItemSet.GetItemState( RES_PARATR_LIST_LEVEL, FALSE, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxInt16Item* pListLevelItem =
+ dynamic_cast<const SfxInt16Item*>(pItem);
+ if ( pListLevelItem->GetValue() != mrTxtNode.GetAttrListLevel() )
+ {
+ mbUpdateListLevel = true;
+ }
+ }
+
+ // handle RES_PARATR_LIST_ISRESTART
+ if ( rItemSet.GetItemState( RES_PARATR_LIST_ISRESTART, FALSE, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxBoolItem* pListIsRestartItem =
+ dynamic_cast<const SfxBoolItem*>(pItem);
+ if ( pListIsRestartItem->GetValue() !=
+ (mrTxtNode.IsListRestart() ? TRUE : FALSE) )
+ {
+ mbUpdateListRestart = true;
+ }
+ }
+
+ // handle RES_PARATR_LIST_RESTARTVALUE
+ if ( rItemSet.GetItemState( RES_PARATR_LIST_RESTARTVALUE, FALSE, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxInt16Item* pListRestartValueItem =
+ dynamic_cast<const SfxInt16Item*>(pItem);
+ if ( !mrTxtNode.HasAttrListRestartValue() ||
+ pListRestartValueItem->GetValue() != mrTxtNode.GetAttrListRestartValue() )
+ {
+ mbUpdateListRestart = true;
+ }
+ }
+
+ // handle RES_PARATR_LIST_ISCOUNTED
+ if ( rItemSet.GetItemState( RES_PARATR_LIST_ISCOUNTED, FALSE, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxBoolItem* pIsCountedInListItem =
+ dynamic_cast<const SfxBoolItem*>(pItem);
+ if ( pIsCountedInListItem->GetValue() !=
+ (mrTxtNode.IsCountedInList() ? TRUE : FALSE) )
+ {
+ mbUpdateListCount = true;
+ }
+ }
+
+ // --> OD 2008-11-19 #i70748#
+ // handle RES_PARATR_OUTLINELEVEL
+ if ( rItemSet.GetItemState( RES_PARATR_OUTLINELEVEL, FALSE, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxUInt16Item* pOutlineLevelItem =
+ dynamic_cast<const SfxUInt16Item*>(pItem);
+ if ( pOutlineLevelItem->GetValue() != mrTxtNode.GetAttrOutlineLevel() )
+ {
+ mbOutlineLevelSet = true;
+ }
+ }
+ // <--
+ }
+
+ HandleSetAttrAtTxtNode::~HandleSetAttrAtTxtNode()
+ {
+ if ( mbAddTxtNodeToList )
+ {
+ SwNumRule* pNumRuleAtTxtNode = mrTxtNode.GetNumRule();
+ if ( pNumRuleAtTxtNode )
+ {
+ mrTxtNode.AddToList();
+ }
+ }
+ else
+ {
+ if ( mbUpdateListLevel && mrTxtNode.IsInList() )
+ {
+ const_cast<SwNodeNum*>(mrTxtNode.GetNum())->SetLevelInListTree(
+ mrTxtNode.GetAttrListLevel() );
+ }
+
+ if ( mbUpdateListRestart && mrTxtNode.IsInList() )
+ {
+ SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
+ pNodeNum->InvalidateMe();
+ pNodeNum->NotifyInvalidSiblings();
+ }
+
+ if ( mbUpdateListCount && mrTxtNode.IsInList() )
+ {
+ const_cast<SwNodeNum*>(mrTxtNode.GetNum())->InvalidateAndNotifyTree();
+ }
+ }
+
+ // --> OD 2008-11-19 #i70748#
+ if ( mbOutlineLevelSet )
+ {
+ if ( mrTxtNode.GetAttrOutlineLevel() == 0 )
+ {
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ }
+ else
+ {
+ const SfxPoolItem* pItem = 0;
+ if ( mrTxtNode.GetSwAttrSet().GetItemState( RES_PARATR_NUMRULE,
+ TRUE, &pItem )
+ != SFX_ITEM_SET )
+ {
+ mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
+ }
+ }
+ }
+ // <--
+ }
+ // End of class <HandleSetAttrAtTxtNode>
+}
+
+BOOL SwTxtNode::SetAttr( const SfxPoolItem& pItem )
+{
+ const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
+ mbInSetOrResetAttr = true;
+
+ HandleSetAttrAtTxtNode aHandleSetAttr( *this, pItem );
+
+ BOOL bRet = SwCntntNode::SetAttr( pItem );
+
+ mbInSetOrResetAttr = bOldIsSetOrResetAttr;
+
+ return bRet;
+}
+
+BOOL SwTxtNode::SetAttr( const SfxItemSet& rSet )
+{
+ const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
+ mbInSetOrResetAttr = true;
+
+ HandleSetAttrAtTxtNode aHandleSetAttr( *this, rSet );
+
+ BOOL bRet = SwCntntNode::SetAttr( rSet );
+
+ mbInSetOrResetAttr = bOldIsSetOrResetAttr;
+
+ return bRet;
+}
+
+namespace {
+ // Helper class for special handling of resetting attributes at text node:
+ // In constructor an instance of the helper class recognize whose attributes
+ // are reset and perform corresponding actions before the intrinsic reset of
+ // attributes has been taken place.
+ // In the destructor - after the attributes have been reset at the text
+ // node - corresponding actions are performed.
+ // The following is handled:
+ // (1) When the list style attribute - RES_PARATR_NUMRULE - is reset,
+ // the text is removed from its list before the attributes have been reset.
+ // (2) When the list id attribute - RES_PARATR_LIST_ID - is reset,
+ // the text is removed from its list before the attributes have been reset.
+ // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is reset.
+ // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is reset.
+ // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - is reset.
+ // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is reset.
+ // (7) Reset empty list style, if outline level attribute - RES_PARATR_OUTLINELEVEL - is reset.
+ class HandleResetAttrAtTxtNode
+ {
+ public:
+ HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const USHORT nWhich1,
+ const USHORT nWhich2 );
+ HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SvUShorts& rWhichArr );
+ HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode );
+
+ ~HandleResetAttrAtTxtNode();
+
+ private:
+ SwTxtNode& mrTxtNode;
+ bool mbListStyleOrIdReset;
+ bool mbUpdateListLevel;
+ bool mbUpdateListRestart;
+ bool mbUpdateListCount;
+ };
+
+ HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const USHORT nWhich1,
+ const USHORT nWhich2 )
+ : mrTxtNode( rTxtNode ),
+ mbListStyleOrIdReset( false ),
+ mbUpdateListLevel( false ),
+ mbUpdateListRestart( false ),
+ mbUpdateListCount( false )
+ {
+ bool bRemoveFromList( false );
+ if ( nWhich2 != 0 && nWhich2 > nWhich1 )
+ {
+ // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
+ if ( nWhich1 <= RES_PARATR_NUMRULE && RES_PARATR_NUMRULE <= nWhich2 )
+ {
+ bRemoveFromList = mrTxtNode.GetNumRule() != 0;
+ mbListStyleOrIdReset = true;
+ }
+ else if ( nWhich1 <= RES_PARATR_LIST_ID && RES_PARATR_LIST_ID <= nWhich2 )
+ {
+ bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
+ mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, FALSE ) == SFX_ITEM_SET;
+ // --> OD 2008-10-20 #i92898#
+ mbListStyleOrIdReset = true;
+ // <--
+ }
+
+ if ( !bRemoveFromList )
+ {
+ // RES_PARATR_LIST_LEVEL
+ mbUpdateListLevel = ( nWhich1 <= RES_PARATR_LIST_LEVEL &&
+ RES_PARATR_LIST_LEVEL <= nWhich2 &&
+ mrTxtNode.HasAttrListLevel() );
+
+ // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
+ mbUpdateListRestart =
+ ( nWhich1 <= RES_PARATR_LIST_ISRESTART && RES_PARATR_LIST_ISRESTART <= nWhich2 &&
+ mrTxtNode.IsListRestart() ) ||
+ ( nWhich1 <= RES_PARATR_LIST_RESTARTVALUE && RES_PARATR_LIST_RESTARTVALUE <= nWhich2 &&
+ mrTxtNode.HasAttrListRestartValue() );
+
+ // RES_PARATR_LIST_ISCOUNTED
+ mbUpdateListCount =
+ ( nWhich1 <= RES_PARATR_LIST_ISCOUNTED && RES_PARATR_LIST_ISCOUNTED <= nWhich2 &&
+ !mrTxtNode.IsCountedInList() );
+ }
+
+ // --> OD 2008-11-19 #i70748#
+ // RES_PARATR_OUTLINELEVEL
+ if ( nWhich1 <= RES_PARATR_OUTLINELEVEL && RES_PARATR_OUTLINELEVEL <= nWhich2 )
+ {
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ }
+ // <--
+ }
+ else
+ {
+ // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
+ if ( nWhich1 == RES_PARATR_NUMRULE )
+ {
+ bRemoveFromList = mrTxtNode.GetNumRule() != 0;
+ mbListStyleOrIdReset = true;
+ }
+ else if ( nWhich1 == RES_PARATR_LIST_ID )
+ {
+ bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
+ mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, FALSE ) == SFX_ITEM_SET;
+ // --> OD 2008-10-20 #i92898#
+ mbListStyleOrIdReset = true;
+ // <--
+ }
+ // --> OD 2008-11-19 #i70748#
+ // RES_PARATR_OUTLINELEVEL
+ else if ( nWhich1 == RES_PARATR_OUTLINELEVEL )
+ {
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ }
+ // <--
+
+ if ( !bRemoveFromList )
+ {
+ // RES_PARATR_LIST_LEVEL
+ mbUpdateListLevel = nWhich1 == RES_PARATR_LIST_LEVEL &&
+ mrTxtNode.HasAttrListLevel();
+
+ // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
+ mbUpdateListRestart = ( nWhich1 == RES_PARATR_LIST_ISRESTART &&
+ mrTxtNode.IsListRestart() ) ||
+ ( nWhich1 == RES_PARATR_LIST_RESTARTVALUE &&
+ mrTxtNode.HasAttrListRestartValue() );
+
+ // RES_PARATR_LIST_ISCOUNTED
+ mbUpdateListCount = nWhich1 == RES_PARATR_LIST_ISCOUNTED &&
+ !mrTxtNode.IsCountedInList();
+ }
+ }
+
+ if ( bRemoveFromList && mrTxtNode.IsInList() )
+ {
+ mrTxtNode.RemoveFromList();
+ }
+ }
+
+ HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SvUShorts& rWhichArr )
+ : mrTxtNode( rTxtNode ),
+ mbListStyleOrIdReset( false ),
+ mbUpdateListLevel( false ),
+ mbUpdateListRestart( false ),
+ mbUpdateListCount( false )
+ {
+ bool bRemoveFromList( false );
+ {
+ const USHORT nEnd = rWhichArr.Count();
+ for ( USHORT n = 0; n < nEnd; ++n )
+ {
+ // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
+ if ( rWhichArr[ n ] == RES_PARATR_NUMRULE )
+ {
+ bRemoveFromList = bRemoveFromList ||
+ mrTxtNode.GetNumRule() != 0;
+ mbListStyleOrIdReset = true;
+ }
+ else if ( rWhichArr[ n ] == RES_PARATR_LIST_ID )
+ {
+ bRemoveFromList = bRemoveFromList ||
+ ( mrTxtNode.GetpSwAttrSet() &&
+ mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, FALSE ) == SFX_ITEM_SET );
+ // --> OD 2008-10-20 #i92898#
+ mbListStyleOrIdReset = true;
+ // <--
+ }
+ // --> OD 2008-11-19 #i70748#
+ // RES_PARATR_OUTLINELEVEL
+ else if ( rWhichArr[ n ] == RES_PARATR_OUTLINELEVEL )
+ {
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ }
+ // <--
+
+ if ( !bRemoveFromList )
+ {
+ // RES_PARATR_LIST_LEVEL
+ mbUpdateListLevel = mbUpdateListLevel ||
+ ( rWhichArr[ n ] == RES_PARATR_LIST_LEVEL &&
+ mrTxtNode.HasAttrListLevel() );
+
+ // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
+ mbUpdateListRestart = mbUpdateListRestart ||
+ ( rWhichArr[ n ] == RES_PARATR_LIST_ISRESTART &&
+ mrTxtNode.IsListRestart() ) ||
+ ( rWhichArr[ n ] == RES_PARATR_LIST_RESTARTVALUE &&
+ mrTxtNode.HasAttrListRestartValue() );
+
+ // RES_PARATR_LIST_ISCOUNTED
+ mbUpdateListCount = mbUpdateListCount ||
+ ( rWhichArr[ n ] == RES_PARATR_LIST_ISCOUNTED &&
+ !mrTxtNode.IsCountedInList() );
+ }
+ }
+ }
+
+ if ( bRemoveFromList && mrTxtNode.IsInList() )
+ {
+ mrTxtNode.RemoveFromList();
+ }
+ }
+
+ HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode )
+ : mrTxtNode( rTxtNode ),
+ mbListStyleOrIdReset( false ),
+ mbUpdateListLevel( false ),
+ mbUpdateListRestart( false ),
+ mbUpdateListCount( false )
+ {
+ mbListStyleOrIdReset = true;
+ if ( rTxtNode.IsInList() )
+ {
+ rTxtNode.RemoveFromList();
+ }
+ // --> OD 2008-11-19 #i70748#
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ // <--
+ }
+
+ HandleResetAttrAtTxtNode::~HandleResetAttrAtTxtNode()
+ {
+ if ( mbListStyleOrIdReset && !mrTxtNode.IsInList() )
+ {
+ // check, if in spite of the reset of the list style or the list id
+ // the paragraph still has to be added to a list.
+ if ( mrTxtNode.GetNumRule() &&
+ mrTxtNode.GetListId().Len() > 0 )
+ {
+ // --> OD 2009-01-14 #i96062#
+ // If paragraph has no list level attribute set and list style
+ // is the outline style, apply outline level as the list level.
+ if ( !mrTxtNode.HasAttrListLevel() &&
+ mrTxtNode.GetNumRule()->GetName() ==
+ String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) &&
+ mrTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() )
+ {
+ int nNewListLevel = mrTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
+ if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
+ {
+ mrTxtNode.SetAttrListLevel( nNewListLevel );
+ }
+ }
+ // <--
+ mrTxtNode.AddToList();
+ }
+ // --> OD 2008-11-19 #i70748#
+ else if ( dynamic_cast<const SfxUInt16Item &>(mrTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, FALSE )).GetValue() > 0 )
+ {
+ mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
+ }
+ // <--
+ }
+
+ if ( mrTxtNode.IsInList() )
+ {
+ if ( mbUpdateListLevel )
+ {
+ SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
+ pNodeNum->SetLevelInListTree( mrTxtNode.GetAttrListLevel() );
+ }
+
+ if ( mbUpdateListRestart )
+ {
+ SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
+ pNodeNum->InvalidateMe();
+ pNodeNum->NotifyInvalidSiblings();
+ }
+
+ if ( mbUpdateListCount )
+ {
+ SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
+ pNodeNum->InvalidateAndNotifyTree();
+ }
+ }
+ }
+ // End of class <HandleResetAttrAtTxtNode>
+}
+
+BOOL SwTxtNode::ResetAttr( USHORT nWhich1, USHORT nWhich2 )
+{
+ const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
+ mbInSetOrResetAttr = true;
+
+ HandleResetAttrAtTxtNode aHandleResetAttr( *this, nWhich1, nWhich2 );
+
+ BOOL bRet = SwCntntNode::ResetAttr( nWhich1, nWhich2 );
+
+ mbInSetOrResetAttr = bOldIsSetOrResetAttr;
+
+ return bRet;
+}
+
+BOOL SwTxtNode::ResetAttr( const SvUShorts& rWhichArr )
+{
+ const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
+ mbInSetOrResetAttr = true;
+
+ HandleResetAttrAtTxtNode aHandleResetAttr( *this, rWhichArr );
+
+ BOOL bRet = SwCntntNode::ResetAttr( rWhichArr );
+
+ mbInSetOrResetAttr = bOldIsSetOrResetAttr;
+
+ return bRet;
+}
+
+USHORT SwTxtNode::ResetAllAttr()
+{
+ const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
+ mbInSetOrResetAttr = true;
+
+ HandleResetAttrAtTxtNode aHandleResetAttr( *this );
+
+ USHORT nRet = SwCntntNode::ResetAllAttr();
+
+ mbInSetOrResetAttr = bOldIsSetOrResetAttr;
+
+ return nRet;
+}
+// <--
+
+
+// sw::Metadatable
+::sfx2::IXmlIdRegistry& SwTxtNode::GetRegistry()
+{
+ return GetDoc()->GetXmlIdRegistry();
+}
+
+bool SwTxtNode::IsInClipboard() const
+{
+ return GetDoc()->IsClipBoard();
+}
+
+bool SwTxtNode::IsInUndo() const
+{
+ return &GetNodes() == GetDoc()->GetUndoNds();
+}
+
+bool SwTxtNode::IsInContent() const
+{
+ return !GetDoc()->IsInHeaderFooter( SwNodeIndex(*this) );
+}
+
+#include <unoparagraph.hxx>
+
+using namespace ::com::sun::star;
+
+uno::Reference< rdf::XMetadatable >
+SwTxtNode::MakeUnoObject()
+{
+ const uno::Reference<rdf::XMetadatable> xMeta(
+ SwXParagraph::CreateXParagraph(*GetDoc(), *this), uno::UNO_QUERY);
+ return xMeta;
+}
+