blob: 623de1acf92ba08bc7745ef944fb29c7664b1727 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <hintids.hxx>
#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
#include <com/sun/star/i18n/ScriptType.hdl>
#endif
#include <fmtcntnt.hxx>
#include <txatbase.hxx>
#include <frmatr.hxx>
#include <viscrs.hxx>
#include <callnk.hxx>
#include <crsrsh.hxx>
#include <doc.hxx>
#include <frmfmt.hxx>
#include <txtfrm.hxx>
#include <ndtxt.hxx>
#include <flyfrm.hxx>
#include <breakit.hxx>
SwCallLink::SwCallLink( SwCrsrShell & rSh, sal_uLong nAktNode, xub_StrLen nAktCntnt,
sal_uInt8 nAktNdTyp, long nLRPos, bool bAktSelection )
: rShell( rSh ), nNode( nAktNode ), nCntnt( nAktCntnt ),
nNdTyp( nAktNdTyp ), nLeftFrmPos( nLRPos ),
bHasSelection( bAktSelection )
{
}
SwCallLink::SwCallLink( SwCrsrShell & rSh )
: rShell( rSh )
{
// SPoint-Werte vom aktuellen Cursor merken
SwPaM* pCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
SwNode& rNd = pCrsr->GetPoint()->nNode.GetNode();
nNode = rNd.GetIndex();
nCntnt = pCrsr->GetPoint()->nContent.GetIndex();
nNdTyp = rNd.GetNodeType();
bHasSelection = ( *pCrsr->GetPoint() != *pCrsr->GetMark() );
if( ND_TEXTNODE & nNdTyp )
nLeftFrmPos = SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)rNd, nCntnt,
!rShell.ActionPend() );
else
{
nLeftFrmPos = 0;
// eine Sonderbehandlung fuer die SwFeShell: diese setzt beim Loeschen
// der Kopf-/Fusszeile, Fussnoten den Cursor auf NULL (Node + Content)
// steht der Cursor auf keinem CntntNode, wird sich das im NdType
// gespeichert.
if( ND_CONTENTNODE & nNdTyp )
nNdTyp = 0;
}
}
SwCallLink::~SwCallLink()
{
if( !nNdTyp || !rShell.bCallChgLnk ) // siehe ctor
return ;
// wird ueber Nodes getravellt, Formate ueberpruefen und im neuen
// Node wieder anmelden
SwPaM* pCurCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
SwCntntNode * pCNd = pCurCrsr->GetCntntNode();
if( !pCNd )
return;
xub_StrLen nCmp, nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
sal_uInt16 nNdWhich = pCNd->GetNodeType();
sal_uLong nAktNode = pCurCrsr->GetPoint()->nNode.GetIndex();
// melde die Shell beim akt. Node als abhaengig an, dadurch koennen
// alle Attribut-Aenderungen ueber den Link weiter gemeldet werden.
pCNd->Add( &rShell );
if( nNdTyp != nNdWhich || nNode != nAktNode )
{
/* immer, wenn zwischen Nodes gesprungen wird, kann es
* vorkommen, das neue Attribute gelten; die Text-Attribute.
* Es muesste also festgestellt werden, welche Attribute
* jetzt gelten; das kann auch gleich der Handler machen
*/
rShell.CallChgLnk();
}
else if( !bHasSelection != !(*pCurCrsr->GetPoint() != *pCurCrsr->GetMark()) )
{
// always call change link when selection changes
rShell.CallChgLnk();
}
else if( rShell.aChgLnk.IsSet() && ND_TEXTNODE == nNdWhich &&
nCntnt != nAktCntnt )
{
// nur wenn mit Left/right getravellt, dann Text-Hints pruefen
// und sich nicht der Frame geaendert hat (Spalten!)
if( nLeftFrmPos == SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)*pCNd, nAktCntnt,
!rShell.ActionPend() ) &&
(( nCmp = nCntnt ) + 1 == nAktCntnt || // Right
nCntnt -1 == ( nCmp = nAktCntnt )) ) // Left
{
if( nCmp == nAktCntnt && pCurCrsr->HasMark() ) // left & Sele
++nCmp;
if ( ((SwTxtNode*)pCNd)->HasHints() )
{
const SwpHints &rHts = ((SwTxtNode*)pCNd)->GetSwpHints();
sal_uInt16 n;
xub_StrLen nStart;
const xub_StrLen *pEnd;
for( n = 0; n < rHts.Count(); n++ )
{
const SwTxtAttr* pHt = rHts[ n ];
pEnd = pHt->End();
nStart = *pHt->GetStart();
// nur Start oder Start und Ende gleich, dann immer
// beim Ueberlaufen von Start callen
if( ( !pEnd || ( nStart == *pEnd ) ) &&
( nStart == nCntnt || nStart == nAktCntnt) )
{
rShell.CallChgLnk();
return;
}
// hat das Attribut einen Bereich und dieser nicht leer
else if( pEnd && nStart < *pEnd &&
// dann teste, ob ueber Start/Ende getravellt wurde
( nStart == nCmp ||
( pHt->DontExpand() ? nCmp == *pEnd-1
: nCmp == *pEnd ) ))
{
rShell.CallChgLnk();
return;
}
nStart = 0;
}
}
if( pBreakIt->GetBreakIter().is() )
{
const String& rTxt = ((SwTxtNode*)pCNd)->GetTxt();
if( !nCmp ||
pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp )
!= pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp - 1 ))
{
rShell.CallChgLnk();
return;
}
}
}
else
/* wenn mit Home/End/.. mehr als 1 Zeichen getravellt, dann
* immer den ChgLnk rufen, denn es kann hier nicht
* festgestellt werden, was sich geaendert; etwas kann
* veraendert sein.
*/
rShell.CallChgLnk();
}
const SwFrm* pFrm;
const SwFlyFrm *pFlyFrm;
if( !rShell.ActionPend() && 0 != ( pFrm = pCNd->getLayoutFrm(rShell.GetLayout(),0,0,sal_False) ) &&
0 != ( pFlyFrm = pFrm->FindFlyFrm() ) && !rShell.IsTableMode() )
{
const SwNodeIndex* pIndex = pFlyFrm->GetFmt()->GetCntnt().GetCntntIdx();
ASSERT( pIndex, "Fly ohne Cntnt" );
if (!pIndex)
return;
const SwNode& rStNd = pIndex->GetNode();
if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode ||
nNode > rStNd.EndOfSectionIndex() )
rShell.GetFlyMacroLnk().Call( (void*)pFlyFrm->GetFmt() );
}
}
long SwCallLink::getLayoutFrm( const SwRootFrm* pRoot, SwTxtNode& rNd, xub_StrLen nCntPos, sal_Bool bCalcFrm )
{
SwTxtFrm* pFrm = (SwTxtFrm*)rNd.getLayoutFrm(pRoot,0,0,bCalcFrm), *pNext = pFrm;
if ( pFrm && !pFrm->IsHiddenNow() )
{
if( pFrm->HasFollow() )
while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() ) &&
nCntPos >= pNext->GetOfst() )
pFrm = pNext;
return pFrm->Frm().Left();
}
return 0;
}