diff options
Diffstat (limited to 'bf_sw/source/core/txtnode/sw_thints.cxx')
-rw-r--r-- | bf_sw/source/core/txtnode/sw_thints.cxx | 1881 |
1 files changed, 1881 insertions, 0 deletions
diff --git a/bf_sw/source/core/txtnode/sw_thints.cxx b/bf_sw/source/core/txtnode/sw_thints.cxx new file mode 100644 index 000000000..00dd00f28 --- /dev/null +++ b/bf_sw/source/core/txtnode/sw_thints.cxx @@ -0,0 +1,1881 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifdef _MSC_VER +#pragma hdrstop +#endif + +#include <hintids.hxx> + +#include <bf_svtools/whiter.hxx> +#include <bf_svtools/itemiter.hxx> +#include <bf_svx/langitem.hxx> +#include <bf_svx/emphitem.hxx> + +#include <txtinet.hxx> +#include <txtflcnt.hxx> +#include <fmtanchr.hxx> +#include <fmtfld.hxx> +#include <fmtinfmt.hxx> +#include <txtatr.hxx> +#include <fchrfmt.hxx> +#include <fmtflcnt.hxx> +#include <fmtftn.hxx> +#include <txttxmrk.hxx> +#include <txtrfmrk.hxx> +#include <txtftn.hxx> +#include <txtfld.hxx> +#include <charfmt.hxx> +#include <frmfmt.hxx> +#include <ftnidx.hxx> +#include <breakit.hxx> + +#include <horiornt.hxx> + +#include <doc.hxx> +#include <pam.hxx> +#include <ndtxt.hxx> +#include <hints.hxx> // fuer SwFmtChg +#include <ddefld.hxx> +#include <docufld.hxx> +#include <expfld.hxx> +#include <usrfld.hxx> +#include <poolfmt.hxx> +// OD 26.06.2003 #108784# +#include <dcontact.hxx> + +#include <algorithm> +namespace binfilter { + +#ifdef DBG_UTIL +#define CHECK Check(); +#else +#define CHECK +#endif + +using namespace ::com::sun::star::i18n; + +/************************************************************************* + * SwTxtNode::MakeTxtAttr() + *************************************************************************/ + + // lege ein neues TextAttribut an und fuege es SwpHints-Array ein +/*N*/ SwTxtAttr* SwTxtNode::MakeTxtAttr( const SfxPoolItem& rAttr, +/*N*/ xub_StrLen nStt, xub_StrLen nEnd, BOOL bPool ) +/*N*/ { +/*N*/ // das neue Attribut im Pool anlegen +/*N*/ const SfxPoolItem& rNew = bPool ? GetDoc()->GetAttrPool().Put( rAttr ) : +/*N*/ rAttr; +/*N*/ +/*N*/ SwTxtAttr* pNew = 0; +/*N*/ switch( rNew.Which() ) +/*N*/ { +/*N*/ case RES_CHRATR_CASEMAP: +/*N*/ case RES_CHRATR_COLOR: +/*N*/ case RES_CHRATR_CHARSETCOLOR: +/*N*/ case RES_CHRATR_CONTOUR: +/*N*/ case RES_CHRATR_CROSSEDOUT: +/*N*/ case RES_CHRATR_ESCAPEMENT: +/*N*/ case RES_CHRATR_KERNING: +/*N*/ case RES_CHRATR_SHADOWED: +/*N*/ case RES_CHRATR_AUTOKERN: +/*N*/ case RES_CHRATR_WORDLINEMODE: +/*N*/ case RES_CHRATR_UNDERLINE: +/*N*/ case RES_CHRATR_FONT: +/*N*/ case RES_CHRATR_CTL_FONT: +/*N*/ case RES_CHRATR_CJK_FONT: +/*N*/ case RES_CHRATR_FONTSIZE: +/*N*/ case RES_CHRATR_CTL_FONTSIZE: +/*N*/ case RES_CHRATR_CJK_FONTSIZE: +/*N*/ case RES_CHRATR_LANGUAGE: +/*N*/ case RES_CHRATR_CTL_LANGUAGE: +/*N*/ case RES_CHRATR_CJK_LANGUAGE: +/*N*/ case RES_CHRATR_POSTURE: +/*N*/ case RES_CHRATR_CTL_POSTURE: +/*N*/ case RES_CHRATR_CJK_POSTURE: +/*N*/ case RES_CHRATR_WEIGHT: +/*N*/ case RES_CHRATR_CTL_WEIGHT: +/*N*/ case RES_CHRATR_CJK_WEIGHT: +/*N*/ case RES_CHRATR_EMPHASIS_MARK: +/*N*/ case RES_CHRATR_NOHYPHEN: +/*N*/ case RES_CHRATR_BLINK: +/*N*/ case RES_CHRATR_BACKGROUND: +/*N*/ case RES_CHRATR_ROTATE: +/*N*/ case RES_CHRATR_SCALEW: +/*N*/ case RES_CHRATR_RELIEF: +/*N*/ pNew = new SwTxtAttrEnd( rNew, nStt, nEnd ); +/*N*/ break; +/*N*/ case RES_TXTATR_CHARFMT: +/*N*/ { +/*N*/ SwFmtCharFmt &rFmtCharFmt = (SwFmtCharFmt&) rNew; +/*N*/ if( !rFmtCharFmt.GetCharFmt() ) +/*?*/ rFmtCharFmt.SetCharFmt( GetDoc()->GetDfltCharFmt() ); +/*N*/ +/*N*/ pNew = new SwTxtCharFmt( rFmtCharFmt, nStt, nEnd ); +/*N*/ } +/*N*/ break; +/*N*/ case RES_TXTATR_INETFMT: +/*N*/ pNew = new SwTxtINetFmt( (SwFmtINetFmt&)rNew, nStt, nEnd ); +/*N*/ break; +/*N*/ case RES_TXTATR_FIELD: +/*N*/ pNew = new SwTxtFld( (SwFmtFld&)rNew, nStt ); +/*N*/ break; +/*N*/ case RES_TXTATR_FLYCNT: +/*N*/ { +/*N*/ // erst hier wird das Frame-Format kopiert (mit Inhalt) !! +/*N*/ pNew = new SwTxtFlyCnt( (SwFmtFlyCnt&)rNew, nStt ); +/*N*/ // Kopie von einem Text-Attribut +/*N*/ if( ((SwFmtFlyCnt&)rAttr).GetTxtFlyCnt() ) +/*N*/ // dann muss das Format Kopiert werden +/*N*/ ((SwTxtFlyCnt*)pNew)->CopyFlyFmt( GetDoc() ); +/*N*/ } +/*N*/ break; +/*N*/ case RES_TXTATR_FTN: +/*N*/ pNew = new SwTxtFtn( (SwFmtFtn&)rNew, nStt ); +/*N*/ // ggfs. SeqNo kopieren +/*N*/ if( ((SwFmtFtn&)rAttr).GetTxtFtn() ) +/*?*/ ((SwTxtFtn*)pNew)->SetSeqNo( ((SwFmtFtn&)rAttr).GetTxtFtn()->GetSeqRefNo() ); +/*N*/ break; +/*?*/ case RES_TXTATR_HARDBLANK: +/*?*/ break; +/*?*/ case RES_CHRATR_TWO_LINES: +/*?*/ break; +/*N*/ case RES_TXTATR_REFMARK: +/*N*/ pNew = nStt == nEnd +/*N*/ ? new SwTxtRefMark( (SwFmtRefMark&)rNew, nStt ) +/*N*/ : new SwTxtRefMark( (SwFmtRefMark&)rNew, nStt, &nEnd ); +/*N*/ break; +/*N*/ case RES_TXTATR_TOXMARK: +/*N*/ pNew = new SwTxtTOXMark( (SwTOXMark&)rNew, nStt, &nEnd ); +/*N*/ break; +/*N*/ case RES_UNKNOWNATR_CONTAINER: +/*?*/ case RES_TXTATR_UNKNOWN_CONTAINER: +/*?*/ break; +/*N*/ case RES_TXTATR_CJK_RUBY: +/*N*/ pNew = new SwTxtRuby( (SwFmtRuby&)rNew, nStt, nEnd ); +/*N*/ break; +/*N*/ } +/*N*/ OSL_ENSURE( pNew, "was fuer ein TextAttribut soll hier angelegt werden?" ); +/*N*/ return pNew; +/*N*/ } + +// loesche das Text-Attribut (muss beim Pool abgemeldet werden!) +/*N*/ void SwTxtNode::DestroyAttr( SwTxtAttr* pAttr ) +/*N*/ { +/*N*/ if( pAttr ) +/*N*/ { +/*N*/ // einige Sachen muessen vorm Loeschen der "Format-Attribute" erfolgen +/*N*/ SwDoc* pDoc = GetDoc(); +/*N*/ USHORT nDelMsg = 0; +/*N*/ switch( pAttr->Which() ) +/*N*/ { +/*N*/ case RES_TXTATR_FLYCNT: +/*N*/ { +/*N*/ // siehe auch die Anmerkung "Loeschen von Formaten +/*N*/ // zeichengebundener Frames" in fesh.cxx, SwFEShell::DelFmt() +/*N*/ SwFrmFmt* pFmt = pAttr->GetFlyCnt().GetFrmFmt(); +/*N*/ if( pFmt ) // vom Undo auf 0 gesetzt ?? +/*N*/ pDoc->DelLayoutFmt( (SwFlyFrmFmt*)pFmt ); +/*N*/ } +/*N*/ break; +/*N*/ +/*N*/ case RES_TXTATR_FTN: +/*N*/ ((SwTxtFtn*)pAttr)->SetStartNode( 0 ); +/*N*/ nDelMsg = RES_FOOTNOTE_DELETED; +/*N*/ break; +/*N*/ +/*N*/ case RES_TXTATR_FIELD: +/*N*/ if( !pDoc->IsInDtor() ) +/*N*/ { +/*N*/ // Wenn wir ein HiddenParaField sind, dann muessen wir +/*N*/ // ggf. fuer eine Neuberechnung des Visible-Flags sorgen. +/*N*/ const SwField* pFld = pAttr->GetFld().GetFld(); +/*N*/ +/*N*/ //JP 06-08-95: DDE-Felder bilden eine Ausnahme +/*N*/ OSL_ENSURE( RES_DDEFLD == pFld->GetTyp()->Which() || +/*N*/ this == ((SwTxtFld*)pAttr)->GetpTxtNode(), +/*N*/ "Wo steht denn dieses Feld?" ); +/*N*/ +/*N*/ // bestimmte Felder mussen am Doc das Calculations-Flag updaten +/*N*/ switch( pFld->GetTyp()->Which() ) +/*N*/ { +/*?*/ case RES_HIDDENPARAFLD: +/*?*/ SetCalcVisible(); +/*?*/ // kein break ! +/*?*/ case RES_DBSETNUMBERFLD: +/*?*/ case RES_GETEXPFLD: +/*?*/ case RES_DBFLD: +/*?*/ case RES_SETEXPFLD: +/*?*/ case RES_HIDDENTXTFLD: +/*?*/ case RES_DBNUMSETFLD: +/*?*/ case RES_DBNEXTSETFLD: +/*?*/ if( !pDoc->IsNewFldLst() && GetNodes().IsDocNodes() ) +/*?*/ pDoc->InsDelFldInFldLst( FALSE, *(SwTxtFld*)pAttr ); +/*?*/ break; +/*?*/ case RES_DDEFLD: +/*?*/ if( GetNodes().IsDocNodes() && +/*?*/ ((SwTxtFld*)pAttr)->GetpTxtNode() ) +/*?*/ ((SwDDEFieldType*)pFld->GetTyp())->DecRefCnt(); +/*?*/ break; +/*N*/ } +/*N*/ } +/*N*/ nDelMsg = RES_FIELD_DELETED; +/*N*/ break; +/*N*/ +/*N*/ case RES_TXTATR_TOXMARK: +/*N*/ nDelMsg = RES_TOXMARK_DELETED; +/*N*/ break; +/*N*/ +/*N*/ case RES_TXTATR_REFMARK: +/*N*/ nDelMsg = RES_REFMARK_DELETED; +/*N*/ break; +/*N*/ } +/*N*/ +/*N*/ if( nDelMsg && !pDoc->IsInDtor() && GetNodes().IsDocNodes() ) +/*N*/ { +/*N*/ SwPtrMsgPoolItem aMsgHint( nDelMsg, (void*)&pAttr->GetAttr() ); +/*N*/ pDoc->GetUnoCallBack()->Modify( &aMsgHint, &aMsgHint ); +/*N*/ } +/*N*/ +/*N*/ pAttr->RemoveFromPool( pDoc->GetAttrPool() ); +/*N*/ delete pAttr; +/*N*/ } +/*N*/ } + +/************************************************************************* + * SwTxtNode::Insert() + *************************************************************************/ + +// lege ein neues TextAttribut an und fuege es ins SwpHints-Array ein +/*N*/ SwTxtAttr* SwTxtNode::Insert( const SfxPoolItem& rAttr, +/*N*/ xub_StrLen nStt, xub_StrLen nEnd, USHORT nMode ) +/*N*/ { +/*N*/ SwTxtAttr* pNew = MakeTxtAttr( rAttr, nStt, nEnd ); +/*N*/ return (pNew && Insert( pNew, nMode )) ? pNew : 0; +/*N*/ } + +// uebernehme den Pointer auf das Text-Attribut + +/*N*/ BOOL SwTxtNode::Insert( SwTxtAttr *pAttr, USHORT nMode ) +/*N*/ { +/*N*/ BOOL bHiddenPara = FALSE; +/*N*/ +/*N*/ OSL_ENSURE( *pAttr->GetStart() <= Len(), "StartIdx hinter Len!" ); +/*N*/ +/*N*/ if( !pAttr->GetEnd() ) +/*N*/ { +/*N*/ USHORT nInsMode = nMode; +/*N*/ switch( pAttr->Which() ) +/*N*/ { +/*N*/ case RES_TXTATR_FLYCNT: +/*N*/ { +/*N*/ SwTxtFlyCnt *pFly = (SwTxtFlyCnt *)pAttr; +/*N*/ SwFrmFmt* pFmt = pAttr->GetFlyCnt().GetFrmFmt(); +/*N*/ if( !(SETATTR_NOTXTATRCHR & nInsMode) ) +/*N*/ { +/*N*/ // Wir muessen zuerst einfuegen, da in SetAnchor() +/*N*/ // dem FlyFrm GetStart() uebermittelt wird. +/*N*/ //JP 11.05.98: falls das Anker-Attribut schon richtig +/*N*/ // gesetzt ist, dann korrigiere dieses nach dem Einfuegen +/*N*/ // des Zeichens. Sonst muesste das immer ausserhalb +/*N*/ // erfolgen (Fehleranfaellig !) +/*N*/ const SwFmtAnchor* pAnchor = 0; +/*N*/ pFmt->GetItemState( RES_ANCHOR, FALSE, +/*N*/ (const SfxPoolItem**)&pAnchor ); +/*N*/ +/*N*/ SwIndex aIdx( this, *pAttr->GetStart() ); +/*N*/ Insert( GetCharOfTxtAttr(*pAttr), aIdx ); +/*N*/ nInsMode |= SETATTR_NOTXTATRCHR; +/*N*/ +/*N*/ if( pAnchor && FLY_IN_CNTNT == pAnchor->GetAnchorId() && +/*N*/ pAnchor->GetCntntAnchor() && +/*N*/ pAnchor->GetCntntAnchor()->nNode == *this && +/*N*/ pAnchor->GetCntntAnchor()->nContent == aIdx ) +/*N*/ ((SwIndex&)pAnchor->GetCntntAnchor()->nContent)--; +/*N*/ } +/*N*/ pFly->SetAnchor( this ); +/*N*/ +/*N*/ // Format-Pointer kann sich im SetAnchor geaendert haben! +/*N*/ // (Kopieren in andere Docs!) +/*N*/ pFmt = pAttr->GetFlyCnt().GetFrmFmt(); +/*N*/ SwDoc *pDoc = pFmt->GetDoc(); +/*N*/ +/*N*/ // OD 26.06.2003 #108784# - allow drawing objects in header/footer. +/*N*/ // But don't allow control objects in header/footer +/*N*/ if( RES_DRAWFRMFMT == pFmt->Which() && +/*N*/ pDoc->IsInHeaderFooter( pFmt->GetAnchor().GetCntntAnchor()->nNode ) ) +/*N*/ { +/*N*/ SwDrawContact* pDrawContact = +/*N*/ static_cast<SwDrawContact*>(pFmt->FindContactObj()); +/*N*/ if ( pDrawContact && +/*N*/ pDrawContact->GetMaster() && +/*N*/ ::binfilter::CheckControlLayer( pDrawContact->GetMaster() ) ) +/*N*/ { +/*N*/ // das soll nicht meoglich sein; hier verhindern +/*N*/ // Der Dtor des TxtHints loescht nicht das Zeichen. +/*N*/ // Wenn ein CH_TXTATR_.. vorliegt, dann muss man +/*N*/ // dieses explizit loeschen +/*?*/ if( SETATTR_NOTXTATRCHR & nInsMode ) +/*?*/ { +/*?*/ // loesche das Zeichen aus dem String ! +/*?*/ OSL_ENSURE( ( CH_TXTATR_BREAKWORD == +/*?*/ aText.GetChar(*pAttr->GetStart() ) || +/*?*/ CH_TXTATR_INWORD == +/*?*/ aText.GetChar(*pAttr->GetStart())), +/*?*/ "where is my attribu character" ); +/*?*/ aText.Erase( *pAttr->GetStart(), 1 ); +/*?*/ // Indizies Updaten +/*?*/ SwIndex aTmpIdx( this, *pAttr->GetStart() ); +/*?*/ Update( aTmpIdx, 1, TRUE ); +/*?*/ } +/*?*/ DestroyAttr( pAttr ); +/*?*/ return FALSE; +/*N*/ } +/*N*/ } +/*N*/ break; +/*N*/ } +/*N*/ case RES_TXTATR_FTN : +/*N*/ { +/*N*/ // Fussnoten, man kommt an alles irgendwie heran. +/*N*/ // CntntNode erzeugen und in die Inserts-Section stellen +/*N*/ SwDoc *pDoc = GetDoc(); +/*N*/ SwNodes &rNodes = pDoc->GetNodes(); +/*N*/ +/*N*/ // FussNote in nicht Content-/Redline-Bereich einfuegen ?? +/*N*/ if( StartOfSectionIndex() < rNodes.GetEndOfAutotext().GetIndex() ) +/*N*/ { +/*N*/ // das soll nicht meoglich sein; hier verhindern +/*N*/ // Der Dtor des TxtHints loescht nicht das Zeichen. +/*N*/ // Wenn ein CH_TXTATR_.. vorliegt, dann muss man +/*N*/ // dieses explizit loeschen +/*?*/ if( SETATTR_NOTXTATRCHR & nInsMode ) +/*?*/ { +/*?*/ // loesche das Zeichen aus dem String ! +/*?*/ OSL_ENSURE( ( CH_TXTATR_BREAKWORD == +/*?*/ aText.GetChar(*pAttr->GetStart() ) || +/*?*/ CH_TXTATR_INWORD == +/*?*/ aText.GetChar(*pAttr->GetStart())), +/*?*/ "where is my attribu character" ); +/*?*/ aText.Erase( *pAttr->GetStart(), 1 ); +/*?*/ // Indizies Updaten +/*?*/ SwIndex aTmpIdx( this, *pAttr->GetStart() ); +/*?*/ Update( aTmpIdx, 1, TRUE ); +/*?*/ } +/*?*/ DestroyAttr( pAttr ); +/*?*/ return FALSE; +/*N*/ } +/*N*/ +/*N*/ // wird eine neue Fussnote eingefuegt ?? +/*N*/ BOOL bNewFtn = 0 == ((SwTxtFtn*)pAttr)->GetStartNode(); +/*N*/ if( bNewFtn ) +/*N*/ ((SwTxtFtn*)pAttr)->MakeNewTextSection( GetNodes() ); +/*N*/ else if ( !GetpSwpHints() || !GetpSwpHints()->IsInSplitNode() ) +/*N*/ { +/*N*/ // loesche alle Frames der Section, auf die der StartNode zeigt +/*N*/ ULONG nSttIdx = +/*N*/ ((SwTxtFtn*)pAttr)->GetStartNode()->GetIndex(); +/*N*/ ULONG nEndIdx = rNodes[ nSttIdx++ ]->EndOfSectionIndex(); +/*N*/ SwCntntNode* pCNd; +/*N*/ for( ; nSttIdx < nEndIdx; ++nSttIdx ) +/*N*/ if( 0 != ( pCNd = rNodes[ nSttIdx ]->GetCntntNode() )) +/*N*/ pCNd->DelFrms(); +/*N*/ } +/*N*/ +/*N*/ if( !(SETATTR_NOTXTATRCHR & nInsMode) ) +/*N*/ { +/*N*/ // Wir muessen zuerst einfuegen, da sonst gleiche Indizes +/*N*/ // entstehen koennen und das Attribut im _SortArr_ am +/*N*/ // Dokument nicht eingetrage wird. +/*N*/ SwIndex aNdIdx( this, *pAttr->GetStart() ); +/*N*/ Insert( GetCharOfTxtAttr(*pAttr), aNdIdx ); +/*N*/ nInsMode |= SETATTR_NOTXTATRCHR; +/*N*/ } +/*N*/ +/*N*/ // Wir tragen uns am FtnIdx-Array des Docs ein ... +/*N*/ SwTxtFtn* pTxtFtn = 0; +/*N*/ if( !bNewFtn ) +/*N*/ { +/*N*/ // eine alte Ftn wird umgehaengt (z.B. SplitNode) +/*N*/ for( USHORT n = 0; n < pDoc->GetFtnIdxs().Count(); ++n ) +/*?*/ if( pAttr == pDoc->GetFtnIdxs()[n] ) +/*?*/ { +/*?*/ // neuen Index zuweisen, dafuer aus dem SortArray +/*?*/ // loeschen und neu eintragen +/*?*/ pTxtFtn = pDoc->GetFtnIdxs()[n]; +/*?*/ pDoc->GetFtnIdxs().Remove( n ); +/*?*/ break; +/*?*/ } +/*N*/ // wenn ueber Undo der StartNode gesetzt wurde, kann +/*N*/ // der Index noch gar nicht in der Verwaltung stehen !! +/*N*/ } +/*N*/ if( !pTxtFtn ) +/*N*/ pTxtFtn = (SwTxtFtn*)pAttr; +/*N*/ +/*N*/ // fuers Update der Nummern und zum Sortieren +/*N*/ // muss der Node gesetzt sein. +/*N*/ ((SwTxtFtn*)pAttr)->ChgTxtNode( this ); +/*N*/ +/*N*/ // FussNote im Redline-Bereich NICHT ins FtnArray einfuegen! +/*N*/ if( StartOfSectionIndex() > rNodes.GetEndOfRedlines().GetIndex() ) +/*N*/ { +/*N*/ #ifdef DBG_UTIL +/*N*/ const BOOL bSuccess = +/*N*/ #endif +/*N*/ pDoc->GetFtnIdxs().Insert( pTxtFtn ); +/*N*/ #ifdef DBG_UTIL +/*N*/ OSL_ENSURE( bSuccess, "FtnIdx nicht eingetragen." ); +/*N*/ #endif +/*N*/ } +/*N*/ SwNodeIndex aTmpIndex( *this ); +/*N*/ pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex); +/*N*/ ((SwTxtFtn*)pAttr)->SetSeqRefNo(); +/*N*/ } +/*N*/ break; +/*N*/ +/*N*/ case RES_TXTATR_FIELD: +/*N*/ { +/*N*/ // fuer HiddenParaFields Benachrichtigungsmechanismus +/*N*/ // anwerfen +/*N*/ if( RES_HIDDENPARAFLD == +/*N*/ pAttr->GetFld().GetFld()->GetTyp()->Which() ) +/*N*/ bHiddenPara = TRUE; +/*N*/ } +/*N*/ break; +/*N*/ +/*N*/ } +/*N*/ // Fuer SwTxtHints ohne Endindex werden CH_TXTATR_.. +/*N*/ // eingefuegt, aStart muss danach um einen zurueckgesetzt werden. +/*N*/ // Wenn wir im SwTxtNode::Copy stehen, so wurde das Zeichen bereits +/*N*/ // mitkopiert. In solchem Fall ist SETATTR_NOTXTATRCHR angegeben worden. +/*N*/ if( !(SETATTR_NOTXTATRCHR & nInsMode) ) +/*N*/ { +/*N*/ SwIndex aIdx( this, *pAttr->GetStart() ); +/*N*/ Insert( GetCharOfTxtAttr(*pAttr), aIdx ); +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ OSL_ENSURE( *pAttr->GetEnd() <= Len(), "EndIdx hinter Len!" ); +/*N*/ } +/*N*/ +/*N*/ if ( !pSwpHints ) +/*N*/ pSwpHints = new SwpHints(); +/*N*/ +/*N*/ // 4263: AttrInsert durch TextInsert => kein Adjust +/*N*/ pSwpHints->Insert( pAttr, *this, nMode ); +/*N*/ +/*N*/ // 47375: In pSwpHints->Insert wird u.a. Merge gerufen und das Hints-Array +/*N*/ // von ueberfluessigen Hints befreit, dies kann u.U. sogar der frisch +/*N*/ // eingefuegte Hint pAttr sein, der dann zerstoert wird!! +/*N*/ if( USHRT_MAX == pSwpHints->GetPos( pAttr ) ) +/*N*/ return FALSE; +/*N*/ +/*N*/ if(bHiddenPara) +/*N*/ SetCalcVisible(); +/*N*/ return TRUE; +/*N*/ } + +/************************************************************************* + * SwTxtNode::Delete() + *************************************************************************/ + +/*N*/ void SwTxtNode::Delete( SwTxtAttr *pAttr, BOOL bThisOnly ) +/*N*/ { +/*N*/ if ( !pSwpHints ) +/*N*/ return; +/*N*/ if( bThisOnly ) +/*N*/ { +/*?*/ xub_StrLen* pEndIdx = pAttr->GetEnd(); +/*?*/ if( !pEndIdx ) +/*?*/ { +/*?*/ // hat es kein Ende kann es nur das sein, was hier steht! +/*?*/ // Unbedingt Copy-konstruieren! +/*?*/ const SwIndex aIdx( this, *pAttr->GetStart() ); +/*?*/ Erase( aIdx, 1 ); +/*?*/ } +/*?*/ else +/*?*/ { +/*?*/ // den MsgHint jetzt fuettern, weil gleich sind +/*?*/ // Start und End weg. +/*?*/ SwUpdateAttr aHint( *pAttr->GetStart(), *pEndIdx, pAttr->Which() ); +/*?*/ pSwpHints->Delete( pAttr ); +/*?*/ pAttr->RemoveFromPool( GetDoc()->GetAttrPool() ); +/*?*/ delete pAttr; +/*?*/ SwModify::Modify( 0, &aHint ); // die Frames benachrichtigen +/*?*/ +/*?*/ if( pSwpHints && pSwpHints->CanBeDeleted() ) +/*?*/ DELETEZ( pSwpHints ); +/*?*/ } +/*?*/ +/*?*/ return; +/*N*/ } +/*N*/ Delete( pAttr->Which(), *pAttr->GetStart(), *pAttr->GetAnyEnd() ); +/*N*/ } + +/************************************************************************* + * SwTxtNode::Delete() + *************************************************************************/ + +/*N*/ void SwTxtNode::Delete( USHORT nTxtWhich, xub_StrLen nStart, xub_StrLen nEnd ) +/*N*/ { +/*N*/ if ( !pSwpHints ) +/*N*/ return; +/*N*/ +/*N*/ const xub_StrLen *pEndIdx; +/*N*/ const xub_StrLen *pSttIdx; +/*N*/ SwTxtAttr* pTxtHt; +/*N*/ +/*N*/ for( USHORT nPos = 0; pSwpHints && nPos < pSwpHints->Count(); nPos++ ) +/*N*/ { +/*N*/ pTxtHt = pSwpHints->GetHt( nPos ); +/*N*/ const USHORT nWhich = pTxtHt->Which(); +/*N*/ if( nWhich == nTxtWhich && +/*N*/ *( pSttIdx = pTxtHt->GetStart()) == nStart ) +/*N*/ { +/*N*/ pEndIdx = pTxtHt->GetEnd(); +/*N*/ +/*N*/ // Text-Attribute sind voellig dynamisch, so dass diese nur +/*N*/ // mit ihrer Start-Position verglichen werden. +/*N*/ if( !pEndIdx ) +/*N*/ { +/*N*/ // Unbedingt Copy-konstruieren! +/*?*/ const SwIndex aIdx( this, *pSttIdx ); +/*?*/ Erase( aIdx, 1 ); +/*?*/ break; +/*N*/ } +/*N*/ else if( *pEndIdx == nEnd ) +/*N*/ { +/*N*/ // den MsgHint jetzt fuettern, weil gleich sind +/*N*/ // Start und End weg. +/*N*/ // Das CalcVisibleFlag bei HiddenParaFields entfaellt, +/*N*/ // da dies das Feld im Dtor selbst erledigt. +/*N*/ SwUpdateAttr aHint( *pSttIdx, *pEndIdx, nTxtWhich ); +/*N*/ pSwpHints->DeleteAtPos( nPos ); // gefunden, loeschen, +/*N*/ pTxtHt->RemoveFromPool( GetDoc()->GetAttrPool() ); +/*N*/ delete pTxtHt; +/*N*/ SwModify::Modify( 0, &aHint ); // die Frames benachrichtigen +/*N*/ break; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ if( pSwpHints && pSwpHints->CanBeDeleted() ) +/*N*/ DELETEZ( pSwpHints ); +/*N*/ } + +/************************************************************************* + * SwTxtNode::DelSoftHyph() + *************************************************************************/ + +// setze diese Attribute am TextNode. Wird der gesamte Bereich umspannt, +// dann setze sie nur im AutoAttrSet (SwCntntNode:: SetAttr) +/*N*/ BOOL SwTxtNode::SetAttr( const SfxItemSet& rSet, xub_StrLen nStt, +/*N*/ xub_StrLen nEnd, USHORT nMode ) +/*N*/ { +/*N*/ if( !rSet.Count() ) +/*N*/ return FALSE; +/*N*/ +/*N*/ // teil die Sets auf (fuer Selektion in Nodes) +/*N*/ const SfxItemSet* pSet = &rSet; +/*N*/ SfxItemSet aTxtSet( *rSet.GetPool(), RES_TXTATR_BEGIN, RES_TXTATR_END-1 ); +/*N*/ +/*N*/ // gesamter Bereich +/*N*/ if( !nStt && nEnd == aText.Len() && !(nMode & SETATTR_NOFORMATATTR ) ) +/*N*/ { +/*N*/ // sind am Node schon Zeichenvorlagen gesetzt, muss man diese Attribute +/*N*/ // (rSet) immer als TextAttribute setzen, damit sie angezeigt werden. +/*N*/ int bHasCharFmts = FALSE; +/*N*/ if( pSwpHints ) +/*N*/ for( USHORT n = 0; n < pSwpHints->Count(); ++n ) +/*N*/ if( (*pSwpHints)[ n ]->IsCharFmtAttr() ) +/*N*/ { +/*N*/ bHasCharFmts = TRUE; +/*N*/ break; +/*N*/ } +/*N*/ +/*N*/ if( !bHasCharFmts ) +/*N*/ { +/*N*/ aTxtSet.Put( rSet ); +/*N*/ if( aTxtSet.Count() != rSet.Count() ) +/*N*/ { +/*N*/ BOOL bRet = SwCntntNode::SetAttr( rSet ); +/*N*/ if( !aTxtSet.Count() ) +/*N*/ return bRet; +/*N*/ } +/*N*/ pSet = &aTxtSet; +/*N*/ } +/*N*/ } +/*N*/ +/*N*/ if ( !pSwpHints ) +/*N*/ pSwpHints = new SwpHints(); +/*N*/ +/*N*/ USHORT nWhich, nCount = 0; +/*N*/ SwTxtAttr* pNew; +/*N*/ SfxItemIter aIter( *pSet ); +/*N*/ const SfxPoolItem* pItem = aIter.GetCurItem(); +/*N*/ do { +/*N*/ if( pItem && (SfxPoolItem*)-1 != pItem && +/*N*/ (( RES_CHRATR_BEGIN <= ( nWhich = pItem->Which()) && +/*N*/ RES_CHRATR_END > nWhich ) || +/*N*/ ( RES_TXTATR_BEGIN <= nWhich && RES_TXTATR_END > nWhich ) || +/*N*/ ( RES_UNKNOWNATR_BEGIN <= nWhich && RES_UNKNOWNATR_END > nWhich )) ) +/*N*/ { +/*N*/ if( !( RES_TXTATR_CHARFMT == pItem->Which() + && GetDoc()->GetDfltCharFmt()==((SwFmtCharFmt*)pItem)->GetCharFmt() + ) + ) +/*N*/ { +/*N*/ pNew = MakeTxtAttr( *pItem, nStt, nEnd ); +/*N*/ if( pNew ) +/*N*/ { +/*N*/ // Attribut ohne Ende, aber Bereich markiert ? +/*N*/ if( nEnd != nStt && !pNew->GetEnd() ) +/*N*/ { +/*?*/ OSL_ENSURE( !this, "Attribut ohne Ende aber Bereich vorgegeben" ); +/*?*/ DestroyAttr( pNew ); // nicht einfuegen +/*N*/ } +/*N*/ else if( Insert( pNew, nMode )) +/*N*/ ++nCount; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ if( aIter.IsAtEnd() ) +/*N*/ break; +/*?*/ pItem = aIter.NextItem(); +/*N*/ } while( TRUE ); +/*N*/ +/*N*/ if( pSwpHints && pSwpHints->CanBeDeleted() ) +/*?*/ DELETEZ( pSwpHints ); +/*N*/ +/*N*/ return nCount ? TRUE : FALSE; +/*N*/ } + +/*N*/ BOOL lcl_Included( const USHORT nWhich, const SwTxtAttr *pAttr ) +/*N*/ { +/*N*/ #if OSL_DEBUG_LEVEL > 1 +/*N*/ static long nTest = 0; +/*N*/ ++nTest; +/*N*/ #endif +/*N*/ BOOL bRet; +/*N*/ SwCharFmt* pFmt = RES_TXTATR_INETFMT == pAttr->Which() ? +/*N*/ ((SwTxtINetFmt*)pAttr)->GetCharFmt() : +/*N*/ pAttr->GetCharFmt().GetCharFmt(); +/*N*/ if( pFmt ) +/*N*/ bRet = SFX_ITEM_SET == pFmt->GetAttrSet().GetItemState( nWhich, TRUE ); +/*N*/ else +/*N*/ bRet = FALSE; +/*N*/ return bRet; +/*N*/ } + +/*N*/ void lcl_MergeAttr( SfxItemSet& rSet, const SfxPoolItem& rAttr ) +/*N*/ { +/*N*/ rSet.Put( rAttr ); +/*N*/ } + +/*N*/ void lcl_MergeAttr_ExpandChrFmt( SfxItemSet& rSet, const SfxPoolItem& rAttr ) +/*N*/ { +/*N*/ if( RES_TXTATR_CHARFMT == rAttr.Which() || +/*N*/ RES_TXTATR_INETFMT == rAttr.Which() ) +/*N*/ { +/*N*/ // aus der Vorlage die Attribute holen: +/*N*/ SwCharFmt* pFmt = RES_TXTATR_INETFMT == rAttr.Which() ? +/*N*/ ((SwFmtINetFmt&)rAttr).GetTxtINetFmt()->GetCharFmt() : +/*N*/ ((SwFmtCharFmt&)rAttr).GetCharFmt(); +/*N*/ if( pFmt ) +/*N*/ { +/*N*/ const SfxItemSet& rCFSet = pFmt->GetAttrSet(); +/*N*/ SfxWhichIter aIter( rCFSet ); +/*N*/ register USHORT nWhich = aIter.FirstWhich(); +/*N*/ while( nWhich ) +/*N*/ { +/*N*/ if( ( nWhich < RES_CHRATR_END ) && +/*N*/ ( SFX_ITEM_SET == rCFSet.GetItemState( nWhich, TRUE ) ) ) +/*N*/ rSet.Put( rCFSet.Get( nWhich ) ); +/*N*/ nWhich = aIter.NextWhich(); +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ +/*N*/ // aufnehmen als MergeWert (falls noch nicht gesetzt neu setzen!) + /* wenn mehrere Attribute ueberlappen gewinnt der letze !! + z.B + 1234567890123456789 + |------------| Font1 + |------| Font2 + ^ ^ + |--| Abfragebereich: -> Gueltig ist Font2 + */ +/*N*/ rSet.Put( rAttr ); +/*N*/ } + +// erfrage die Attribute vom TextNode ueber den Bereich +/*N*/ BOOL SwTxtNode::GetAttr( SfxItemSet& rSet, xub_StrLen nStart, xub_StrLen nEnd, +/*N*/ BOOL bOnlyTxtAttr, BOOL bGetFromChrFmt ) const +/*N*/ { +/*N*/ if( pSwpHints ) +/*N*/ { + /* stelle erstmal fest, welche Text-Attribut in dem Bereich gueltig + * sind. Dabei gibt es folgende Faelle: + * UnEindeutig wenn: (wenn != Format-Attribut) + * - das Attribut liegt vollstaendig im Bereich + * - das Attributende liegt im Bereich + * - der Attributanfang liegt im Bereich: + * Eindeutig (im Set mergen): + * - das Attrib umfasst den Bereich + * nichts tun: + * das Attribut liegt ausserhalb des Bereiches + */ +/*N*/ +/*N*/ void (*fnMergeAttr)( SfxItemSet&, const SfxPoolItem& ) +/*N*/ = bGetFromChrFmt ? &lcl_MergeAttr_ExpandChrFmt +/*N*/ : &lcl_MergeAttr; +/*N*/ +/*N*/ // dann besorge mal die Auto-(Fmt)Attribute +/*N*/ SfxItemSet aFmtSet( *rSet.GetPool(), rSet.GetRanges() ); +/*N*/ if( !bOnlyTxtAttr ) +/*N*/ SwCntntNode::GetAttr( aFmtSet ); +/*N*/ +/*N*/ const USHORT nSize = pSwpHints->Count(); +/*N*/ register USHORT n; +/*N*/ register xub_StrLen nAttrStart; +/*N*/ register const xub_StrLen* pAttrEnd; +/*N*/ +/*N*/ if( nStart == nEnd ) // kein Bereich: +/*N*/ { +/*N*/ for( n = 0; n < nSize; ++n ) // +/*N*/ { +/*N*/ const SwTxtAttr* pHt = (*pSwpHints)[n]; +/*N*/ nAttrStart = *pHt->GetStart(); +/*N*/ if( nAttrStart > nEnd ) // ueber den Bereich hinaus +/*N*/ break; +/*N*/ +/*N*/ if( 0 == ( pAttrEnd = pHt->GetEnd() )) // nie Attribute ohne Ende +/*N*/ continue; +/*N*/ +/*N*/ if( ( nAttrStart < nStart && +/*N*/ ( pHt->DontExpand() ? nStart < *pAttrEnd +/*N*/ : nStart <= *pAttrEnd )) || +/*N*/ ( nStart == nAttrStart && +/*N*/ ( nAttrStart == *pAttrEnd || !nStart ))) +/*N*/ (*fnMergeAttr)( rSet, pHt->GetAttr() ); +/*N*/ } +/*N*/ } +/*N*/ else // es ist ein Bereich definiert +/*N*/ { +/*N*/ SwTxtAttr** aAttrArr = 0; +/*N*/ const USHORT coArrSz = RES_TXTATR_WITHEND_END - RES_CHRATR_BEGIN + +/*N*/ ( RES_UNKNOWNATR_END - +/*N*/ RES_UNKNOWNATR_BEGIN ); +/*N*/ +/*N*/ for( n = 0; n < nSize; ++n ) +/*N*/ { +/*N*/ const SwTxtAttr* pHt = (*pSwpHints)[n]; +/*N*/ nAttrStart = *pHt->GetStart(); +/*N*/ if( nAttrStart > nEnd ) // ueber den Bereich hinaus +/*N*/ break; +/*N*/ +/*N*/ if( 0 == ( pAttrEnd = pHt->GetEnd() )) // nie Attribute ohne Ende +/*N*/ continue; +/*N*/ +/*N*/ BOOL bChkInvalid = FALSE; +/*N*/ if( nAttrStart <= nStart ) // vor oder genau Start +/*N*/ { +/*N*/ if( *pAttrEnd <= nStart ) // liegt davor +/*N*/ continue; +/*N*/ +/*N*/ if( nEnd <= *pAttrEnd ) // hinter oder genau Ende +/*N*/ (*fnMergeAttr)( aFmtSet, pHt->GetAttr() ); +/*N*/ else +/*N*/ // uneindeutig +/*N*/ bChkInvalid = TRUE; +/*N*/ } +/*N*/ else if( nAttrStart < nEnd ) // reicht in den Bereich +/*N*/ bChkInvalid = TRUE; +/*N*/ +/*N*/ if( bChkInvalid ) +/*N*/ { +/*?*/ // uneindeutig ? +/*?*/ if( !aAttrArr ) +/*?*/ { +/*?*/ aAttrArr = new SwTxtAttr* [ coArrSz ]; +/*?*/ memset( aAttrArr, 0, sizeof( SwTxtAttr* ) * coArrSz ); +/*?*/ } +/*?*/ +/*?*/ const SwTxtAttr** ppPrev; +/*?*/ if( RES_CHRATR_BEGIN <= pHt->Which() && +/*?*/ pHt->Which() < RES_TXTATR_WITHEND_END ) +/*?*/ ppPrev = (const SwTxtAttr**)&aAttrArr[ +/*?*/ pHt->Which() - RES_CHRATR_BEGIN ]; +/*?*/ else if( RES_UNKNOWNATR_BEGIN <= pHt->Which() && +/*?*/ pHt->Which() < RES_UNKNOWNATR_END ) +/*?*/ ppPrev = (const SwTxtAttr**)&aAttrArr[ +/*?*/ pHt->Which() - RES_UNKNOWNATR_BEGIN +/*?*/ + ( RES_TXTATR_WITHEND_END - +/*?*/ RES_CHRATR_BEGIN ) ]; +/*?*/ else +/*?*/ ppPrev = 0; +/*?*/ +/*?*/ if( !*ppPrev ) +/*?*/ { +/*?*/ if( nAttrStart > nStart ) +/*?*/ { +/*?*/ rSet.InvalidateItem( pHt->Which() ); +/*?*/ *ppPrev = (SwTxtAttr*)-1; +/*?*/ } +/*?*/ else +/*?*/ *ppPrev = pHt; +/*?*/ } +/*?*/ else if( (SwTxtAttr*)-1 != *ppPrev ) +/*?*/ { +/*?*/ if( *(*ppPrev)->GetEnd() == nAttrStart && +/*?*/ (*ppPrev)->GetAttr() == pHt->GetAttr() ) +/*?*/ *ppPrev = pHt; +/*?*/ else +/*?*/ { +/*?*/ rSet.InvalidateItem( pHt->Which() ); +/*?*/ *ppPrev = (SwTxtAttr*)-1; +/*?*/ } +/*?*/ } +/*N*/ } +/*N*/ } +/*N*/ if( aAttrArr ) +/*N*/ { +/*?*/ const SwTxtAttr* pAttr; +/*?*/ for( n = 0; n < coArrSz; ++n ) +/*?*/ if( 0 != ( pAttr = aAttrArr[ n ] ) && +/*?*/ (SwTxtAttr*)-1 != pAttr ) +/*?*/ { +/*?*/ USHORT nWh; +/*?*/ if( n < (RES_TXTATR_WITHEND_END - +/*?*/ RES_CHRATR_BEGIN )) +/*?*/ nWh = n + RES_CHRATR_BEGIN; +/*?*/ else +/*?*/ nWh = n - ( RES_TXTATR_WITHEND_END - +/*?*/ RES_CHRATR_BEGIN ) + +/*?*/ RES_UNKNOWNATR_BEGIN; +/*?*/ +/*?*/ if( nEnd <= *pAttr->GetEnd() ) // hinter oder genau Ende +/*?*/ { +/*?*/ if( pAttr->GetAttr() != aFmtSet.Get( nWh ) ) +/*?*/ (*fnMergeAttr)( rSet, pAttr->GetAttr() ); +/*?*/ } +/*?*/ else +/*?*/ // uneindeutig +/*?*/ rSet.InvalidateItem( nWh ); +/*?*/ } +/*?*/ delete [] aAttrArr; +/*N*/ } +/*N*/ } +/*N*/ if( aFmtSet.Count() ) +/*N*/ { +/*N*/ // aus dem Format-Set alle entfernen, die im TextSet auch gesetzt sind +/*N*/ aFmtSet.Differentiate( rSet ); +/*N*/ // jetzt alle zusammen "mergen" +/*N*/ rSet.Put( aFmtSet ); +/*N*/ } +/*N*/ } +/*N*/ else if( !bOnlyTxtAttr ) +/*N*/ // dann besorge mal die Auto-(Fmt)Attribute +/*N*/ SwCntntNode::GetAttr( rSet ); +/*N*/ +/*N*/ return rSet.Count() ? TRUE : FALSE; +/*N*/ } + +/*N*/ void SwTxtNode::FmtToTxtAttr( SwTxtNode* pNd ) +/*N*/ { +/*N*/ SfxItemSet aThisSet( GetDoc()->GetAttrPool(), aCharFmtSetRange ); +/*N*/ if( GetpSwAttrSet() && GetpSwAttrSet()->Count() ) +/*?*/ aThisSet.Put( *GetpSwAttrSet() ); +/*N*/ +/*N*/ if ( !pSwpHints ) +/*N*/ pSwpHints = new SwpHints(); +/*N*/ +/*N*/ if( pNd == this ) +/*N*/ { +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ SfxItemSet aNdSet( pNd->GetDoc()->GetAttrPool(), aCharFmtSetRange ); +/*N*/ if( pNd->GetpSwAttrSet() && pNd->GetpSwAttrSet()->Count() ) +/*?*/ aNdSet.Put( *pNd->GetpSwAttrSet() ); +/*N*/ +/*N*/ if ( !pNd->pSwpHints ) +/*N*/ pNd->pSwpHints = new SwpHints(); +/*N*/ } +/*N*/ +/*N*/ if( pNd->pSwpHints->CanBeDeleted() ) +/*N*/ DELETEZ( pNd->pSwpHints ); +/*N*/ } + +/************************************************************************* + * SwpHints::CalcFlags() + *************************************************************************/ + +/*N*/ void SwpHints::CalcFlags() +/*N*/ { +/*N*/ bDDEFlds = bFtn = FALSE; +/*N*/ const USHORT nSize = Count(); +/*N*/ const SwTxtAttr* pAttr; +/*N*/ for( USHORT nPos = 0; nPos < nSize; ++nPos ) +/*N*/ switch( ( pAttr = (*this)[ nPos ])->Which() ) +/*N*/ { +/*N*/ case RES_TXTATR_FTN: +/*N*/ bFtn = TRUE; +/*N*/ if( bDDEFlds ) +/*N*/ return; +/*N*/ break; +/*N*/ case RES_TXTATR_FIELD: +/*N*/ { +/*N*/ const SwField* pFld = pAttr->GetFld().GetFld(); +/*N*/ if( RES_DDEFLD == pFld->GetTyp()->Which() ) +/*N*/ { +/*N*/ bDDEFlds = TRUE; +/*N*/ if( bFtn ) +/*N*/ return; +/*N*/ } +/*N*/ } +/*N*/ break; +/*N*/ } +/*N*/ } + +/************************************************************************* + * SwpHints::CalcVisibleFlag() + *************************************************************************/ + +/*N*/ BOOL SwpHints::CalcVisibleFlag() +/*N*/ { +/*N*/ BOOL bOldVis = bVis; +/*N*/ bCalcVis = FALSE; +/*N*/ BOOL bNewVis = TRUE; +/*N*/ const USHORT nSize = Count(); +/*N*/ const SwTxtAttr *pTxtHt; +/*N*/ +/*N*/ for( USHORT nPos = 0; nPos < nSize; ++nPos ) +/*N*/ { +/*N*/ pTxtHt = (*this)[ nPos ]; +/*N*/ const USHORT nWhich = pTxtHt->Which(); +/*N*/ +/*N*/ if( RES_TXTATR_FIELD == nWhich ) +/*N*/ { +/*N*/ const SwFmtFld& rFld = pTxtHt->GetFld(); +/*N*/ if( RES_HIDDENPARAFLD == rFld.GetFld()->GetTyp()->Which()) +/*N*/ { +/*N*/ if( !((SwHiddenParaField*)rFld.GetFld())->IsHidden() ) +/*N*/ { +/*N*/ SetVisible(TRUE); +/*N*/ return !bOldVis; +/*N*/ } +/*N*/ else +/*N*/ bNewVis = FALSE; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ SetVisible( bNewVis ); +/*N*/ return bOldVis != bNewVis; +/*N*/ } + +/************************************************************************* + * SwpHints::Resort() + *************************************************************************/ + +// Ein Hint hat seinen Anfangswert geaendert. +// Hat sich dadurch die Sortierreihenfolge +// geaendert, so wird solange umsortiert, bis +// sie wieder stimmt. + +/*N*/ BOOL SwpHints::Resort( const USHORT nPos ) +/*N*/ { +/*N*/ const SwTxtAttr *pTmp; +/*N*/ +/*N*/ if ( ( nPos+1 < Count() && +/*N*/ *(*this)[nPos]->GetStart() > *(*this)[nPos+1]->GetStart() ) || +/*N*/ ( nPos > 0 && +/*N*/ *(*this)[nPos]->GetStart() < *(*this)[nPos-1]->GetStart() ) ) +/*N*/ { +/*?*/ pTmp = (*this)[nPos]; +/*?*/ DeleteAtPos( nPos ); +/*?*/ SwpHintsArr::Insert( pTmp ); +/*?*/ // Wenn tatsaechlich umsortiert wurde, muss die +/*?*/ // Position i nochmal bearbeitet werden. +/*?*/ return TRUE; +/*N*/ } +/*N*/ return FALSE; +/*N*/ } + +/************************************************************************* + * SwpHints::ClearDummies() + *************************************************************************/ + +/* + * ClearDummies: Hints, die genau den gleichen Bereich umfassen wie + * ein nachfolgender mit gleichem Attribut oder eine nachfolgende Zeichen- + * vorlage, muessen entfernt werden. + * Solche Hints entstehen, wenn sie urspruenglich einen groesseren, den + * Nachfolger umfassenden Bereich hatten, die Aussenanteile aber durch + * SwTxtNode::RstAttr oder SwTxtNode::Update geloescht wurden. + */ + +/*N*/ void SwpHints::ClearDummies( SwTxtNode &rNode ) +/*N*/ { +/*N*/ USHORT i = 0; +/*N*/ while ( i < Count() ) +/*N*/ { +/*N*/ SwTxtAttr *pHt = GetHt( i++ ); +/*N*/ const USHORT nWhich = pHt->Which(); +/*N*/ const xub_StrLen *pEnd = pHt->GetEnd(); +/*N*/ if ( pEnd && !pHt->IsOverlapAllowedAttr() && !pHt->IsCharFmtAttr() ) +/*N*/ for( USHORT j = i; j < Count(); ++j ) +/*N*/ { +/*N*/ SwTxtAttr *pOther = GetHt(j); +/*N*/ if ( *pOther->GetStart() > *pHt->GetStart() ) +/*N*/ break; +/*N*/ +/*N*/ if( pOther->Which() == nWhich || pOther->IsCharFmtAttr() ) +/*N*/ { +/*N*/ //JP 03.10.95: nicht zusammenfassen, zu kompliziert +/*N*/ // fuer WIN95-Compiler!! +/*?*/ if( *pEnd == *pOther->GetEnd() && +/*?*/ ( pOther->Which() == nWhich || +/*?*/ lcl_Included( nWhich, pOther ) ) ) +/*?*/ { +/*?*/ rNode.DestroyAttr( Cut( --i ) ); +/*?*/ break; +/*?*/ } +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ } + +/************************************************************************* + * SwpHints::Merge( ) + *************************************************************************/ + +/* + * Merge: Gleichartigen, gleichwertige Hints, die aneinandergrenzen, + * koennen verschmolzen werden, wenn an ihrer gemeinsamen Kante nicht ein + * gleichartiges Attribut endet oder beginnt, welches einen von der beiden + * Kandidaten umfasst, auch Zeichenvorlage duerfen nicht ueberlappt werden. + */ + +/* + * And here a smarter version of good old Merge(..) + * If a SwTxtAttr is given, only the merging between this attribute and the + * neighbours are checked. This saves time, if no attribute is given (in more + * complex situations), the whole attribute array is checked as before. + */ + +/*N*/ BOOL SwpHints::Merge( SwTxtNode &rNode, SwTxtAttr* pAttr ) +/*N*/ { +/*N*/ USHORT i; +/*N*/ BOOL bMerged = FALSE; +/*N*/ if( pAttr && USHRT_MAX != ( i = GetPos( pAttr ) ) ) +/*N*/ { +/*N*/ const xub_StrLen *pEnd = pAttr->GetEnd(); +/*N*/ if ( pEnd && !pAttr->IsDontMergeAttr() ) +/*N*/ { +/*N*/ USHORT j = i; +/*N*/ const USHORT nWhich = pAttr->Which(); +/*N*/ const USHORT nStart = *pAttr->GetStart(); +/*N*/ const USHORT nEnd = *pEnd; +/*N*/ SwTxtAttr *pPrev; +/*N*/ SwTxtAttr *pNext; +/*N*/ USHORT nEndIdx = aHtEnd.C40_GETPOS( SwTxtAttr, pAttr ); +/*N*/ OSL_ENSURE( USHRT_MAX != nEndIdx, "Missing end index" ); +/*N*/ if( nEndIdx ) +/*N*/ { +/*N*/ // If there's a attribute with same start and which-id, +/*N*/ // it's not possible to merge with a previous attribute. +/*N*/ pPrev = pAttr; +/*N*/ while( j ) +/*N*/ { +/*N*/ SwTxtAttr *pOther = GetHt(--j); +/*N*/ if ( *pOther->GetStart() < nStart ) +/*N*/ break; +/*N*/ if( pOther->Which() == nWhich || pOther->IsCharFmtAttr() +/*N*/ || pAttr->IsCharFmtAttr() ) +/*N*/ { +/*N*/ pPrev = NULL; +/*N*/ break; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ pPrev = NULL; +/*N*/ if( i + 1 < Count() ) +/*N*/ { +/*N*/ // If there's a attribute with same end and which-id, +/*N*/ // it's not possible to merge with a following attribute. +/*N*/ j = nEndIdx + 1; +/*N*/ pNext = pAttr; +/*N*/ while( j < Count() ) +/*N*/ { +/*N*/ SwTxtAttr *pOther = GetEnd( j++ ); +/*N*/ if( !pOther->GetEnd() ) +/*N*/ continue; +/*N*/ if( *pOther->GetEnd() > nEnd ) +/*N*/ break; +/*N*/ if( pOther->Which() == nWhich || pOther->IsCharFmtAttr() +/*N*/ || pAttr->IsCharFmtAttr() ) +/*N*/ { +/*N*/ pNext = NULL; +/*N*/ break; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ pNext = NULL; +/*N*/ if( pPrev ) +/*N*/ { +/*N*/ pPrev = NULL; +/*N*/ j = nEndIdx; +/*N*/ do +/*N*/ { +/*N*/ // Looking for a previous attribute with the same which-id +/*N*/ // which ends exact at the start of the given attribute +/*N*/ SwTxtAttr *pOther = GetEnd( --j ); +/*N*/ pEnd = pOther->GetEnd(); +/*N*/ if( !pEnd || *pEnd > nStart ) +/*N*/ continue; +/*N*/ if( *pEnd < nStart ) +/*N*/ break; +/*N*/ if( pOther->Which() == nWhich ) +/*N*/ { +/*N*/ if( pOther->GetAttr() == pAttr->GetAttr() ) +/*N*/ { +/*N*/ bMerged = TRUE; +/*N*/ pPrev = pOther; +/*N*/ } +/*N*/ else +/*N*/ pPrev = NULL; +/*N*/ break; +/*N*/ } +/*N*/ if( pOther->IsCharFmtAttr() || pAttr->IsCharFmtAttr() ) +/*N*/ { +/*N*/ pPrev = NULL; +/*N*/ break; +/*N*/ } +/*N*/ } while ( j ); +/*N*/ } +/*N*/ if( pNext ) +/*N*/ { +/*N*/ j = i + 1; +/*N*/ pNext = NULL; +/*N*/ while( j < Count() ) +/*N*/ { +/*N*/ // Looking for a following attribute with the same which-id +/*N*/ // which starts at the end of the given attribute +/*N*/ SwTxtAttr *pOther = GetStart( j++ ); +/*N*/ pEnd = pOther->GetEnd(); +/*N*/ if( !pEnd || *pOther->GetStart() < nEnd ) +/*N*/ continue; +/*N*/ if( *pOther->GetStart() > nEnd ) +/*N*/ break; +/*N*/ if( pOther->Which() == nWhich ) +/*N*/ { +/*N*/ if( pOther->GetAttr() == pAttr->GetAttr() ) +/*N*/ { +/*N*/ bMerged = TRUE; +/*N*/ pNext = pOther; +/*N*/ } +/*N*/ else +/*N*/ pNext = NULL; +/*N*/ break; +/*N*/ } +/*?*/ if( pOther->IsCharFmtAttr() || pAttr->IsCharFmtAttr() ) +/*?*/ { +/*?*/ pNext = NULL; +/*?*/ break; +/*?*/ } +/*N*/ } +/*N*/ } +/*N*/ if( bMerged ) +/*N*/ { +/*N*/ if( pNext ) +/*N*/ { +/*N*/ if ( pPrev == pNext ) +/*N*/ pPrev = NULL; +/*N*/ +/*?*/ *pAttr->GetEnd() = *pNext->GetEnd(); +/*?*/ pAttr->SetDontExpand( FALSE ); +/*?*/ rNode.DestroyAttr( Cut( j - 1 ) ); +/*N*/ } +/*N*/ if( pPrev ) +/*N*/ { +/*N*/ *pPrev->GetEnd() = *pAttr->GetEnd(); +/*N*/ pPrev->SetDontExpand( FALSE ); +/*N*/ rNode.DestroyAttr( Cut( i ) ); +/*N*/ } +/*N*/ return TRUE; +/*N*/ } +/*N*/ return FALSE; +/*N*/ } +/*N*/ } +/*N*/ i = 0; +/*N*/ while ( i < Count() ) +/*N*/ { +/*N*/ SwTxtAttr *pHt = GetHt( i++ ); +/*N*/ const xub_StrLen *pEnd = pHt->GetEnd(); +/*N*/ if ( pEnd && !pHt->IsDontMergeAttr() ) +/*N*/ { +/*N*/ const USHORT nWhich = pHt->Which(); +/*N*/ for ( USHORT j = i; j < Count(); j++ ) +/*N*/ { +/*N*/ SwTxtAttr *pOther = GetHt(j); +/*N*/ if ( *pOther->GetStart() > *pEnd ) +/*N*/ break; // keine beruehrenden Attribute mehr vorhanden +/*N*/ +/*N*/ if( *pOther->GetStart() == *pEnd && +/*N*/ ( pOther->Which() == nWhich || +/*N*/ pOther->IsCharFmtAttr() || +/*N*/ ( pHt->IsCharFmtAttr() && !pHt->IsDontMergeAttr() ))) +/*N*/ { +/*?*/ // Beruehrendes Attribut gefunden mit gleichem Typ bzw. +/*?*/ // Zeichenvorlage. +/*?*/ // Bei Attribut mit anderem Wert bzw. Zeichenvorlage +/*?*/ // ist keine Verschmelzung mehr moeglich +/*?*/ if( pOther->Which() == nWhich && +/*?*/ pOther->GetAttr() == pHt->GetAttr() ) +/*?*/ { +/*?*/ // Unser Partner pOther erfuellt alle Voraussetzungen, +/*?*/ // jetzt muessen wir uns selbst noch ueberpruefen, ob wir +/*?*/ // nicht von einem gleichartigen Attribut oder einer +/*?*/ // Zeichenvorlage umfasst werden, die das gleiche Ende +/*?*/ // wie wir selbst haben. +/*?*/ BOOL bMerge = TRUE; +/*?*/ for ( USHORT k = 0; k+1 < i; k++ ) +/*?*/ { +/*?*/ SwTxtAttr *pAnOther = GetHt(k); +/*?*/ if( ( pAnOther->Which() == nWhich || +/*?*/ pAnOther->IsCharFmtAttr() || +/*?*/ pHt->IsCharFmtAttr() ) +/*?*/ && pAnOther->GetEnd() +/*?*/ && *pAnOther->GetEnd() == *pEnd ) +/*?*/ { +/*?*/ bMerge = FALSE; // kein Verschmelzen von i+j +/*?*/ break; +/*?*/ } +/*?*/ } +/*?*/ if ( bMerge ) +/*?*/ { +/*?*/ *pHt->GetEnd() = *pOther->GetEnd(); +/*?*/ pHt->SetDontExpand( FALSE ); +/*?*/ rNode.DestroyAttr( Cut( j ) ); +/*?*/ --i; +/*?*/ bMerged = TRUE; +/*?*/ } +/*?*/ } +/*?*/ break; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ if ( bMerged ) +/*?*/ ClearDummies( rNode ); +/*N*/ return bMerged; +/*N*/ } + +/************************************************************************* + * SwpHints::Insert() + *************************************************************************/ + +/* + * Insert: Der neue Hint wird immer eingefuegt. Wenn dabei ein + * ueberlappender oder gleicher Hintbereich mit gleichem Attribut + * und Wert gefunden, wird der neue Hint entsprechend veraendert + * und der alte herausgenommen (und zerstoert: + * SwpHints::Destroy()). + */ + +/*N*/ void SwpHints::Insert( SwTxtAttr *pHint, SwTxtNode &rNode, USHORT nMode ) +/*N*/ { +/*N*/ // Irgendwann ist immer Schluss +/*N*/ if( USHRT_MAX == Count() ) +/*N*/ return; +/*N*/ +/*N*/ // Felder bilden eine Ausnahme: +/*N*/ // 1) Sie koennen nie ueberlappen +/*N*/ // 2) Wenn zwei Felder genau aneinander liegen, +/*N*/ // sollen sie nicht zu einem verschmolzen werden. +/*N*/ // Wir koennen also auf die while-Schleife verzichten +/*N*/ +/*N*/ xub_StrLen *pHtEnd = pHint->GetEnd(); +/*N*/ USHORT nWhich = pHint->Which(); +/*N*/ +/*N*/ switch( nWhich ) +/*N*/ { +/*N*/ case RES_TXTATR_CHARFMT: +/*N*/ ((SwTxtCharFmt*)pHint)->ChgTxtNode( &rNode ); +/*N*/ break; +/*N*/ case RES_TXTATR_INETFMT: +/*N*/ { +/*N*/ ((SwTxtINetFmt*)pHint)->ChgTxtNode( &rNode ); +/*N*/ SwCharFmt* pFmt = rNode.GetDoc()->GetCharFmtFromPool( RES_POOLCHR_INET_NORMAL ); +/*N*/ pFmt->Add( (SwTxtINetFmt*)pHint ); +/*N*/ } +/*N*/ break; +/*N*/ case RES_TXTATR_FIELD: +/*N*/ { +/*N*/ BOOL bDelFirst = 0 != ((SwTxtFld*)pHint)->GetpTxtNode(); +/*N*/ ((SwTxtFld*)pHint)->ChgTxtNode( &rNode ); +/*N*/ SwDoc* pDoc = rNode.GetDoc(); +/*N*/ const SwField* pFld = ((SwTxtFld*)pHint)->GetFld().GetFld(); +/*N*/ +/*N*/ if( !pDoc->IsNewFldLst() ) +/*N*/ { +/*N*/ // was fuer ein Feld ist es denn ?? +/*N*/ // bestimmte Felder mussen am Doc das Calculations-Flag updaten +/*N*/ switch( pFld->GetTyp()->Which() ) +/*N*/ { +/*N*/ case RES_DBFLD: +/*N*/ case RES_SETEXPFLD: +/*N*/ case RES_HIDDENPARAFLD: +/*N*/ case RES_HIDDENTXTFLD: +/*N*/ case RES_DBNUMSETFLD: +/*N*/ case RES_DBNEXTSETFLD: +/*N*/ { +/*N*/ if( bDelFirst ) +/*?*/ pDoc->InsDelFldInFldLst( FALSE, *(SwTxtFld*)pHint ); +/*N*/ if( rNode.GetNodes().IsDocNodes() ) +/*N*/ pDoc->InsDelFldInFldLst( TRUE, *(SwTxtFld*)pHint ); +/*N*/ } +/*N*/ break; +/*?*/ case RES_DDEFLD: +/*?*/ if( rNode.GetNodes().IsDocNodes() ) +/*?*/ ((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt(); +/*?*/ break; +/*N*/ } +/*N*/ } +/*N*/ +/*N*/ // gehts ins normale Nodes-Array? +/*N*/ if( rNode.GetNodes().IsDocNodes() ) +/*N*/ { +/*N*/ switch( pFld->GetTyp()->Which() ) +/*N*/ { +/*N*/ case RES_SETEXPFLD: +/*N*/ if( GSE_SEQ & ((SwSetExpFieldType*)pFld->GetTyp())->GetType() ) +/*N*/ { +/*N*/ // bevor die ReferenzNummer gesetzt wird, sollte +/*N*/ // das Feld am richtigen FeldTypen haengen! +/*N*/ SwSetExpFieldType* pFldType = (SwSetExpFieldType*) +/*N*/ pDoc->InsertFldType( *pFld->GetTyp() ); +/*N*/ pFldType->SetSeqRefNo( *(SwSetExpField*)pFld ); +/*N*/ } +/*N*/ break; +/*N*/ case RES_USERFLD: +/*N*/ break; +/*N*/ +/*N*/ case RES_DDEFLD: +/*N*/ if( pDoc->IsNewFldLst() ) +/*N*/ ((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt(); +/*N*/ break; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ break; +/*N*/ case RES_TXTATR_FTN : +/*N*/ ((SwTxtFtn*)pHint)->ChgTxtNode( &rNode ); +/*N*/ break; +/*N*/ case RES_TXTATR_REFMARK: +/*N*/ ((SwTxtRefMark*)pHint)->ChgTxtNode( &rNode ); +/*N*/ break; +/*N*/ case RES_TXTATR_TOXMARK: +/*N*/ ((SwTxtTOXMark*)pHint)->ChgTxtNode( &rNode ); +/*N*/ break; +/*N*/ +/*N*/ case RES_TXTATR_CJK_RUBY: +/*N*/ break; +/*N*/ } +/*N*/ +/*N*/ if( SETATTR_DONTEXPAND & nMode ) +/*N*/ pHint->SetDontExpand( TRUE ); +/*N*/ +/*N*/ // SwTxtAttrs ohne Ende werden sonderbehandelt: +/*N*/ // Sie werden natuerlich in das Array insertet, aber sie werden nicht +/*N*/ // in die pPrev/Next/On/Off-Verkettung aufgenommen. +/*N*/ // Der Formatierer erkennt diese TxtHints an dem CH_TXTATR_.. im Text ! +/*N*/ xub_StrLen nHtStart = *pHint->GetStart(); +/*N*/ if( !pHtEnd ) +/*N*/ { +/*N*/ SwpHintsArr::Insert( pHint ); +/*N*/ CalcFlags(); +/*N*/ #ifdef DBG_UTIL +/*N*/ if( !rNode.GetDoc()->IsInReading() ) +/*N*/ CHECK; +/*N*/ #endif +/*N*/ // ... und die Abhaengigen benachrichtigen +/*N*/ if ( rNode.GetDepends() ) +/*N*/ { +/*N*/ SwUpdateAttr aHint( nHtStart, nHtStart, nWhich ); +/*N*/ rNode.Modify( 0, &aHint ); +/*N*/ } +/*N*/ return; +/*N*/ } +/*N*/ +/*N*/ // ---------------------------------------------------------------- +/*N*/ // Ab hier gibt es nur noch pHint mit einem EndIdx !!! +/*N*/ +/*N*/ SwTxtAttr *pMerge = pHint; // For a smarter Merge-function +/*N*/ +/*N*/ BOOL bResort = FALSE; +/*N*/ +/*N*/ if( *pHtEnd < nHtStart ) +/*N*/ { +/*?*/ OSL_ENSURE( *pHtEnd >= nHtStart, +/*?*/ "+SwpHints::Insert: invalid hint, end < start" ); +/*?*/ +/*?*/ // Wir drehen den Quatsch einfach um: +/*?*/ *pHint->GetStart() = *pHtEnd; +/*?*/ *pHtEnd = nHtStart; +/*?*/ nHtStart = *pHint->GetStart(); +/*N*/ } +/*N*/ +/*N*/ // AMA: Damit wir endlich mit ueberlappenden Hints fertig werden ... +/*N*/ // das neue Verfahren: +/*N*/ +/*N*/ if( !(SETATTR_NOHINTADJUST & nMode) && !pHint->IsOverlapAllowedAttr() ) +/*N*/ { +/*N*/ const SfxPoolItem* pParaItem; +/*N*/ xub_StrLen nMaxEnd = *pHtEnd; +/*N*/ xub_StrLen nHtEnd = *pHtEnd; +/*N*/ BOOL bParaAttr = rNode.GetpSwAttrSet() && +/*N*/ ( SFX_ITEM_SET == rNode.GetpSwAttrSet()->GetItemState( nWhich, +/*N*/ FALSE, &pParaItem ) ) && ( pParaItem == &pHint->GetAttr() ); +/*N*/ BOOL bReplace = !( SETATTR_DONTREPLACE & nMode ); +/*N*/ ::binfilter::SwpHtStart_SAR *pTmpHints = 0; +/*N*/ +/*N*/ USHORT i; +/*N*/ // Wir wollen zwar von nHtStart bis nMaxEnd, muessen aber ggf. +/*N*/ // stueckeln (Attribute duerfen keine Zeichenvorlagen ueberlappen). +/*N*/ // Das erste Stueck wird also von nHtStart bis zum ersten Start/Ende +/*N*/ // einer Zeichenvorlage gehen usw. bis nHtEnd = nMaxEnd erreicht ist. +/*N*/ do { +/*N*/ BOOL bINet = nWhich == RES_TXTATR_INETFMT; +/*N*/ BOOL bForgetAttr = bParaAttr; +/*N*/ // Muessen wir uns aufspalten? +/*N*/ if ( !bINet && !pHint->IsDontMergeAttr() ) +/*N*/ { +/*N*/ // Ab der zweiten Runde muessen wir zunaechst einen neuen +/*N*/ // Hint erzeugen. +/*N*/ if ( nHtEnd != nMaxEnd ) +/*N*/ { +/*?*/ pMerge = NULL; // No way to use the smarter Merge() +/*?*/ pHint = rNode.MakeTxtAttr( bParaAttr ? *pParaItem : +/*?*/ pHint->GetAttr(), +/*?*/ nHtStart, nMaxEnd ); +/*?*/ nHtEnd = *pHint->GetEnd(); +/*N*/ } +/*N*/ +/*N*/ for ( i = 0; i < Count(); i++) +/*N*/ { +/*N*/ SwTxtAttr *pOther = GetHt(i); +/*N*/ // Wir suchen nach Zeichenvorlagen, die uns schneiden +/*N*/ // oder in uns liegen +/*N*/ BOOL bOtherFmt = pOther->IsCharFmtAttr(); +/*N*/ if( bOtherFmt || +/*N*/ ( RES_TXTATR_CHARFMT == nWhich && pOther->GetEnd() ) ) +/*N*/ { +/*N*/ if( bForgetAttr && bOtherFmt && +/*N*/ *pOther->GetStart() <= nHtStart && +/*N*/ *pOther->GetEnd() >= nHtStart ) +/*N*/ bForgetAttr = FALSE; + /* Die Flags bCheckInclude und bOtherFmt sollen die + * Anzahl der Aufrufe von lcl_Include minimieren, da + * dieses wg. IsVisitedURL() teuer ist. */ +/*N*/ BOOL bCheckInclude = FALSE; +/*N*/ if( *pOther->GetStart() > nHtStart +/*N*/ && *pOther->GetStart() < nHtEnd +/*N*/ && ( bReplace || *pOther->GetEnd() > nHtEnd ) ) +/*N*/ { +/*?*/ if( bOtherFmt ) +/*?*/ nHtEnd = *pOther->GetStart(); +/*N*/ } +/*N*/ if( *pOther->GetEnd() > nHtStart +/*N*/ && *pOther->GetEnd() < nHtEnd +/*N*/ && ( bReplace || *pOther->GetStart() < nHtStart ) ) +/*N*/ { +/*?*/ if( bOtherFmt || ( !bCheckInclude && +/*?*/ !lcl_Included( pOther->Which(), pHint ) ) ) +/*?*/ nHtEnd = *pOther->GetEnd(); +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ *pHint->GetEnd() = nHtEnd; +/*N*/ } +/*N*/ +/*N*/ i = 0; +/*N*/ while(i < Count()) +/*N*/ { +/*N*/ SwTxtAttr *pOther = GetHt(i); +/*N*/ const USHORT nOtherWhich = pOther->Which(); +/*N*/ BOOL bCheckInclude = pHint->IsCharFmtAttr() && +/*N*/ pOther->IsCharFmtAttr() && +/*N*/ nWhich != nOtherWhich; +/*N*/ +/*N*/ BOOL bOtherCharFmt = RES_TXTATR_CHARFMT == nOtherWhich; +/*N*/ if( nOtherWhich == nWhich || bCheckInclude ) +/*N*/ { +/*N*/ if(0 == pOther->GetEnd()) +/*N*/ { +/*?*/ if( *pOther->GetStart() == nHtStart && +/*?*/ nOtherWhich == nWhich && +/*?*/ pOther->GetAttr() == pHint->GetAttr() ) +/*?*/ { +/*?*/ // Gibts schon, alten raus. +/*?*/ rNode.DestroyAttr( Cut(i) ); +/*?*/ } +/*?*/ else +/*?*/ ++i; +/*?*/ continue; +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ // Attribute mit Anfang und Ende. +/*N*/ const Range aHintRg( nHtStart, nHtEnd ); +/*N*/ const Range aOtherRg( *pOther->GetStart(), +/*N*/ *pOther->GetEnd() ); +/*N*/ +/*N*/ if( aOtherRg.IsInside( aHintRg.Min() ) || +/*N*/ aHintRg.IsInside( aOtherRg.Min() ) ) +/*N*/ { +/*N*/ // aBig umspannt beide Ranges +/*N*/ const Range aBig( +/*N*/ Min( aHintRg.Min(), aOtherRg.Min()), +/*N*/ Max( aHintRg.Max(), aOtherRg.Max())); +/*N*/ +/*N*/ // Gleiches Attribut +/*N*/ // oder Zeichenvorlage: +/*N*/ // Bereiche duerfen nicht ueberlappen. +/*N*/ +/*N*/ // Zuerst wurde geprueft, ob sich der neue mit dem +/*N*/ // alten ueberschneidet, danach gibt es nur noch +/*N*/ // drei Faelle zu beachten: +/*N*/ // 1) der neue umschliesst den alten +/*N*/ // 2) der neue ueberlappt den alten hinten +/*N*/ // 3) der neue ueberlappt den alten vorne +/*N*/ +/*N*/ BOOL bNoINet = RES_TXTATR_INETFMT != nOtherWhich || +/*N*/ nWhich == nOtherWhich; +/*N*/ +/*N*/ // 1) der neue umschliesst den alten +/*N*/ if( aBig == aHintRg ) +/*N*/ { +/*N*/ BOOL bTmpReplace = bReplace || +/*N*/ ( aHintRg == aOtherRg && +/*N*/ nWhich == nOtherWhich && +/*N*/ !pHint->IsCharFmtAttr() ); +/*N*/ if( bNoINet && bTmpReplace && +/*N*/ ( !bOtherCharFmt || nWhich == nOtherWhich ) ) +/*N*/ { +/*N*/ if( !bCheckInclude || +/*N*/ lcl_Included( nOtherWhich, pHint ) ) +/*N*/ { +/*N*/ rNode.DestroyAttr( Cut(i) ); +/*N*/ } +/*N*/ else +/*N*/ ++i; +/*N*/ continue; +/*N*/ } +/*N*/ } +/*N*/ else if( !bReplace && aBig == aOtherRg ) +/*?*/ bForgetAttr = FALSE; +/*N*/ // 2) der neue ueberlappt hinten +/*N*/ else if( aBig.Max() == aHintRg.Max() ) +/*N*/ { +/*N*/ if( bNoINet && +/*N*/ ( !bOtherCharFmt || RES_TXTATR_CHARFMT != nWhich ) && +/*N*/ ( bReplace || aHintRg.Max() != aOtherRg.Max() ) ) +/*N*/ { +/*N*/ if( ( bCheckInclude && +/*N*/ lcl_Included( nOtherWhich, pHint ) ) || +/*N*/ ( !bCheckInclude && !bOtherCharFmt ) ) +/*N*/ { +/*N*/ if( nMaxEnd == nHtStart ) +/*N*/ bForgetAttr = FALSE; +/*N*/ *pOther->GetEnd() = nHtStart; +/*N*/ bResort = TRUE; +/*N*/ // ChainDelEnd( pOther ); +/*N*/ // ChainEnds( pOther ); +/*N*/ } +/*N*/ else if( bINet && +/*N*/ aHintRg.Max() != aOtherRg.Max() && +/*N*/ aHintRg.Min() < aOtherRg.Max() ) +/*N*/ { +/*N*/ // Wenn ein INetFmt eingefuegt wird, muss +/*N*/ // sich ein anderes Attribut ggf. aufspal- +/*N*/ // ten. Es wird beiseite gestellt und in +/*N*/ // einem spaeteren Durchgang eingefuegt. +/*N*/ // Beim Einfuegen spaltet es sich selbst. +/*?*/ if( !pTmpHints ) +/*?*/ pTmpHints = new ::binfilter::SwpHtStart_SAR(); +/*?*/ pTmpHints->C40_INSERT( SwTxtAttr, pOther, +/*?*/ pTmpHints->Count() ); +/*?*/ Cut( i ); +/*?*/ continue; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ // 3) der neue ueberlappt vorne +/*N*/ else if( aBig.Min() == aHintRg.Min() ) +/*N*/ { +/*N*/ if( bNoINet && +/*N*/ ( RES_TXTATR_CHARFMT != nOtherWhich || +/*N*/ RES_TXTATR_CHARFMT != nWhich ) && +/*N*/ ( bReplace || aHintRg.Min() != aOtherRg.Min() ) ) +/*N*/ { +/*N*/ if( ( bCheckInclude && +/*N*/ lcl_Included( nOtherWhich, pHint ) ) || +/*N*/ ( !bCheckInclude && !bOtherCharFmt ) ) +/*N*/ { +/*N*/ +/*N*/ *pOther->GetStart() = nHtEnd; +/*N*/ +/*N*/ // ChainDelStart( pOther ); +/*N*/ // ChainStarts( pOther ); +/*N*/ +/*N*/ const BOOL bOk = Resort(i); +/*N*/ if( bOk ) +/*N*/ continue; +/*N*/ } +/*N*/ else if( bINet && +/*N*/ aHintRg.Min() != aOtherRg.Min() && +/*N*/ aHintRg.Max() > aOtherRg.Min() ) +/*N*/ { +/*?*/ // Wenn ein INetFmt eingefuegt wird, muss +/*?*/ // sich ein anderes Attribut ggf. aufspal- +/*?*/ // ten. Es wird beiseite gestellt und in +/*?*/ // einem spaeteren Durchgang eingefuegt. +/*?*/ // Beim Einfuegen spaltet es sich selbst. +/*?*/ if( !pTmpHints ) +/*?*/ pTmpHints = new ::binfilter::SwpHtStart_SAR(); +/*?*/ pTmpHints->C40_INSERT( SwTxtAttr, pOther, +/*?*/ pTmpHints->Count() ); +/*?*/ Cut( i ); +/*?*/ continue; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ bForgetAttr = FALSE; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ ++i; +/*N*/ } +/*N*/ +/*N*/ ClearDummies( rNode ); +/*N*/ // Nur wenn wir nicht sowieso schon durch die Absatzattribute +/*N*/ // gueltig sind, werden wir eingefuegt ... +/*N*/ if( bForgetAttr ) +/*N*/ { +/*?*/ rNode.DestroyAttr( pHint ); +/*?*/ pMerge = NULL; // No smart Merge() +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ SwpHintsArr::Insert( pHint ); +/*N*/ bResort = FALSE; +/*N*/ } +/*N*/ // InsertChain( pHint ); +/*N*/ +/*N*/ // ... und die Abhaengigen benachrichtigen +/*N*/ if ( rNode.GetDepends() ) +/*N*/ { +/*N*/ SwUpdateAttr aHint( nHtStart, nHtEnd, nWhich ); +/*N*/ rNode.Modify( 0, &aHint ); +/*N*/ } +/*N*/ // Falls es noch 'ne Runde gibt: +/*N*/ nHtStart = nHtEnd; +/*N*/ if( nMaxEnd > nHtEnd ) +/*N*/ continue; +/*N*/ if( !pTmpHints ) +/*N*/ break; +/*?*/ pMerge = NULL; // No smart Merge() +/*?*/ pHint = pTmpHints->GetObject(0); +/*?*/ nWhich = pHint->Which(); +/*?*/ nHtStart = *pHint->GetStart(); +/*?*/ nHtEnd = *pHint->GetEnd(); +/*?*/ nMaxEnd = nHtEnd; +/*?*/ bParaAttr = FALSE; +/*?*/ pTmpHints->Remove(0); +/*?*/ if( !pTmpHints->Count() ) +/*?*/ { +/*?*/ delete pTmpHints; +/*?*/ pTmpHints = NULL; +/*?*/ } +/*N*/ } while ( TRUE ); +/*N*/ +/*N*/ if( bResort ) +/*?*/ SwpHintsArr::Resort(); +/*N*/ +/*N*/ // Jetzt wollen wir mal gucken, ob wir das SwpHintsArray nicht +/*N*/ // etwas vereinfachen koennen ... +/*N*/ Merge( rNode, pMerge ); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ SwpHintsArr::Insert( pHint ); +/*N*/ // InsertChain( pHint ); +/*N*/ +/*N*/ // ... und die Abhaengigen benachrichtigen +/*N*/ if ( rNode.GetDepends() ) +/*N*/ { +/*N*/ SwUpdateAttr aHint( nHtStart, +/*N*/ nHtStart == *pHtEnd ? *pHtEnd + 1 : *pHtEnd, nWhich ); +/*N*/ rNode.Modify( 0, &aHint ); +/*N*/ } +/*N*/ } +/*N*/ #ifdef DBG_UTIL +/*N*/ if( !rNode.GetDoc()->IsInReading() ) +/*N*/ CHECK; +/*N*/ #endif +/*N*/ } + +/************************************************************************* + * SwpHints::DeleteAtPos() + *************************************************************************/ + +/*N*/ void SwpHints::DeleteAtPos( const USHORT nPos ) +/*N*/ { +/*N*/ SwTxtAttr *pHint = GetHt(nPos); +/*N*/ // ChainDelete( pHint ); +/*N*/ SwpHintsArr::DeleteAtPos( nPos ); +/*N*/ +/*N*/ if( RES_TXTATR_FIELD == pHint->Which() ) +/*N*/ { +/*N*/ SwFieldType* pFldTyp = ((SwTxtFld*)pHint)->GetFld().GetFld()->GetTyp(); +/*N*/ if( RES_DDEFLD == pFldTyp->Which() ) +/*N*/ { +/*?*/ const SwTxtNode* pNd = ((SwTxtFld*)pHint)->GetpTxtNode(); +/*?*/ if( pNd && pNd->GetNodes().IsDocNodes() ) +/*?*/ ((SwDDEFieldType*)pFldTyp)->DecRefCnt(); +/*?*/ ((SwTxtFld*)pHint)->ChgTxtNode( 0 ); +/*N*/ } +/*N*/ else if( !bVis && RES_HIDDENPARAFLD == pFldTyp->Which() ) +/*N*/ bCalcVis = TRUE; +/*N*/ } +/*N*/ CalcFlags(); +/*N*/ CHECK; +/*N*/ } + +// Ist der Hint schon bekannt, dann suche die Position und loesche ihn. +// Ist er nicht im Array, so gibt es ein ASSERT !! + +/*N*/ void SwpHints::Delete( SwTxtAttr* pTxtHt ) +/*N*/ { +/*N*/ // Attr 2.0: SwpHintsArr::Delete( pTxtHt ); +/*N*/ const USHORT nPos = GetStartOf( pTxtHt ); +/*N*/ OSL_ENSURE( USHRT_MAX != nPos, "Attribut nicht im Attribut-Array!" ); +/*N*/ if( USHRT_MAX != nPos ) +/*N*/ DeleteAtPos( nPos ); +/*N*/ } + +/*N*/ #ifdef VERTICAL_LAYOUT +/*N*/ USHORT SwTxtNode::GetLang( const xub_StrLen nBegin, const xub_StrLen nLen, +/*N*/ USHORT nScript ) const +/*N*/ #else +/*N*/ USHORT SwTxtNode::GetLang( const xub_StrLen nBegin, const xub_StrLen nLen) const +/*N*/ #endif +/*N*/ { +/*N*/ USHORT nWhichId = RES_CHRATR_LANGUAGE; +/*N*/ USHORT nRet = LANGUAGE_DONTKNOW; +/*N*/ if( pSwpHints ) +/*N*/ { +/*N*/ #ifdef VERTICAL_LAYOUT +/*N*/ if ( ! nScript ) +/*N*/ nScript = pBreakIt->GetRealScriptOfText( aText, nBegin ); +/*N*/ +/*N*/ nWhichId = GetWhichOfScript( nWhichId, nScript ); +/*N*/ #else +/*N*/ nWhichId = GetWhichOfScript( nWhichId, +/*N*/ pBreakIt->GetRealScriptOfText( aText, nBegin )); +/*N*/ #endif +/*N*/ +/*N*/ xub_StrLen nEnd = nBegin + nLen; +/*N*/ for( USHORT i = 0, nSize = pSwpHints->Count(); i < nSize; ++i ) +/*N*/ { +/*N*/ // ist der Attribut-Anfang schon groesser als der Idx ? +/*N*/ const SwTxtAttr *pHt = pSwpHints->operator[](i); +/*N*/ xub_StrLen nAttrStart = *pHt->GetStart(); +/*N*/ if( nEnd < nAttrStart ) +/*N*/ break; +/*N*/ +/*N*/ const USHORT nWhich = pHt->Which(); +/*N*/ +/*N*/ if( ( pHt->IsCharFmtAttr() && lcl_Included( nWhichId, pHt ) ) +/*N*/ || nWhichId == nWhich ) +/*N*/ { +/*N*/ const xub_StrLen *pEndIdx = pHt->GetEnd(); +/*N*/ // Ueberlappt das Attribut den Bereich? +/*N*/ +/*N*/ if( pEndIdx && +/*N*/ nLen ? ( nAttrStart < nEnd && nBegin < *pEndIdx ) +/*N*/ : (( nAttrStart < nBegin && +/*N*/ ( pHt->DontExpand() ? nBegin < *pEndIdx +/*N*/ : nBegin <= *pEndIdx )) || +/*N*/ ( nBegin == nAttrStart && +/*N*/ ( nAttrStart == *pEndIdx || !nBegin ))) ) +/*N*/ { +/*N*/ const SfxPoolItem* pItem; +/*N*/ if( RES_TXTATR_CHARFMT == nWhich ) +/*N*/ pItem = &pHt->GetCharFmt().GetCharFmt()->GetAttr( nWhichId ); +/*N*/ else if( RES_TXTATR_INETFMT == nWhich ) +/*?*/ pItem = &((SwTxtINetFmt*)pHt)->GetCharFmt()->GetAttr( nWhichId ); +/*N*/ else +/*N*/ pItem = &pHt->GetAttr(); +/*N*/ +/*N*/ USHORT nLng = ((SvxLanguageItem*)pItem)->GetLanguage(); +/*N*/ +/*N*/ // Umfasst das Attribut den Bereich komplett? +/*N*/ if( nAttrStart <= nBegin && nEnd <= *pEndIdx ) +/*N*/ nRet = nLng; +/*N*/ else if( LANGUAGE_DONTKNOW == nRet ) +/*N*/ nRet = nLng; // partielle Ueberlappung, der 1. gewinnt +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ if( LANGUAGE_DONTKNOW == nRet ) +/*N*/ { +/*N*/ if( !pSwpHints ) +/*N*/ nWhichId = GetWhichOfScript( RES_CHRATR_LANGUAGE, +/*N*/ pBreakIt->GetRealScriptOfText( aText, nBegin )); +/*N*/ +/*N*/ nRet = ((SvxLanguageItem&)GetSwAttrSet().Get( nWhichId )).GetLanguage(); +/*N*/ if( LANGUAGE_DONTKNOW == nRet ) +/*N*/ nRet = GetAppLanguage(); +/*N*/ } +/*N*/ return nRet; +/*N*/ } + +/*N*/ sal_Unicode GetCharOfTxtAttr( const SwTxtAttr& rAttr ) +/*N*/ { +/*N*/ sal_Unicode cRet = CH_TXTATR_BREAKWORD; +/*N*/ switch ( rAttr.Which() ) +/*N*/ { +/*N*/ case RES_TXTATR_REFMARK: +/*N*/ case RES_TXTATR_TOXMARK: +/*N*/ case RES_TXTATR_FTN: +/*N*/ cRet = CH_TXTATR_INWORD; +/*N*/ break; +/*N*/ } +/*N*/ return cRet; +/*N*/ } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |