| /************************************************************** |
| * |
| * 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; |
| } |
| |