1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 32 #include <hintids.hxx> 33 34 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_ 35 #include <com/sun/star/i18n/ScriptType.hdl> 36 #endif 37 #include <fmtcntnt.hxx> 38 #include <txatbase.hxx> 39 #include <frmatr.hxx> 40 #include <viscrs.hxx> 41 #include <callnk.hxx> 42 #include <crsrsh.hxx> 43 #include <doc.hxx> 44 #include <frmfmt.hxx> 45 #include <txtfrm.hxx> 46 #include <ndtxt.hxx> 47 #include <flyfrm.hxx> 48 #include <breakit.hxx> 49 50 51 SwCallLink::SwCallLink( SwCrsrShell & rSh, sal_uLong nAktNode, xub_StrLen nAktCntnt, 52 sal_uInt8 nAktNdTyp, long nLRPos, bool bAktSelection ) 53 : rShell( rSh ), nNode( nAktNode ), nCntnt( nAktCntnt ), 54 nNdTyp( nAktNdTyp ), nLeftFrmPos( nLRPos ), 55 bHasSelection( bAktSelection ) 56 { 57 } 58 59 60 SwCallLink::SwCallLink( SwCrsrShell & rSh ) 61 : rShell( rSh ) 62 { 63 // SPoint-Werte vom aktuellen Cursor merken 64 SwPaM* pCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr(); 65 SwNode& rNd = pCrsr->GetPoint()->nNode.GetNode(); 66 nNode = rNd.GetIndex(); 67 nCntnt = pCrsr->GetPoint()->nContent.GetIndex(); 68 nNdTyp = rNd.GetNodeType(); 69 bHasSelection = ( *pCrsr->GetPoint() != *pCrsr->GetMark() ); 70 71 if( ND_TEXTNODE & nNdTyp ) 72 nLeftFrmPos = SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)rNd, nCntnt, 73 !rShell.ActionPend() ); 74 else 75 { 76 nLeftFrmPos = 0; 77 78 // eine Sonderbehandlung fuer die SwFeShell: diese setzt beim Loeschen 79 // der Kopf-/Fusszeile, Fussnoten den Cursor auf NULL (Node + Content) 80 // steht der Cursor auf keinem CntntNode, wird sich das im NdType 81 // gespeichert. 82 if( ND_CONTENTNODE & nNdTyp ) 83 nNdTyp = 0; 84 } 85 } 86 87 88 SwCallLink::~SwCallLink() 89 { 90 if( !nNdTyp || !rShell.bCallChgLnk ) // siehe ctor 91 return ; 92 93 // wird ueber Nodes getravellt, Formate ueberpruefen und im neuen 94 // Node wieder anmelden 95 SwPaM* pCurCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr(); 96 SwCntntNode * pCNd = pCurCrsr->GetCntntNode(); 97 if( !pCNd ) 98 return; 99 100 xub_StrLen nCmp, nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex(); 101 sal_uInt16 nNdWhich = pCNd->GetNodeType(); 102 sal_uLong nAktNode = pCurCrsr->GetPoint()->nNode.GetIndex(); 103 104 // melde die Shell beim akt. Node als abhaengig an, dadurch koennen 105 // alle Attribut-Aenderungen ueber den Link weiter gemeldet werden. 106 pCNd->Add( &rShell ); 107 108 if( nNdTyp != nNdWhich || nNode != nAktNode ) 109 { 110 /* immer, wenn zwischen Nodes gesprungen wird, kann es 111 * vorkommen, das neue Attribute gelten; die Text-Attribute. 112 * Es muesste also festgestellt werden, welche Attribute 113 * jetzt gelten; das kann auch gleich der Handler machen 114 */ 115 rShell.CallChgLnk(); 116 } 117 else if( !bHasSelection != !(*pCurCrsr->GetPoint() != *pCurCrsr->GetMark()) ) 118 { 119 // always call change link when selection changes 120 rShell.CallChgLnk(); 121 } 122 else if( rShell.aChgLnk.IsSet() && ND_TEXTNODE == nNdWhich && 123 nCntnt != nAktCntnt ) 124 { 125 // nur wenn mit Left/right getravellt, dann Text-Hints pruefen 126 // und sich nicht der Frame geaendert hat (Spalten!) 127 if( nLeftFrmPos == SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)*pCNd, nAktCntnt, 128 !rShell.ActionPend() ) && 129 (( nCmp = nCntnt ) + 1 == nAktCntnt || // Right 130 nCntnt -1 == ( nCmp = nAktCntnt )) ) // Left 131 { 132 if( nCmp == nAktCntnt && pCurCrsr->HasMark() ) // left & Sele 133 ++nCmp; 134 if ( ((SwTxtNode*)pCNd)->HasHints() ) 135 { 136 137 const SwpHints &rHts = ((SwTxtNode*)pCNd)->GetSwpHints(); 138 sal_uInt16 n; 139 xub_StrLen nStart; 140 const xub_StrLen *pEnd; 141 142 for( n = 0; n < rHts.Count(); n++ ) 143 { 144 const SwTxtAttr* pHt = rHts[ n ]; 145 pEnd = pHt->GetEnd(); 146 nStart = *pHt->GetStart(); 147 148 // nur Start oder Start und Ende gleich, dann immer 149 // beim Ueberlaufen von Start callen 150 if( ( !pEnd || ( nStart == *pEnd ) ) && 151 ( nStart == nCntnt || nStart == nAktCntnt) ) 152 { 153 rShell.CallChgLnk(); 154 return; 155 } 156 157 // hat das Attribut einen Bereich und dieser nicht leer 158 else if( pEnd && nStart < *pEnd && 159 // dann teste, ob ueber Start/Ende getravellt wurde 160 ( nStart == nCmp || 161 ( pHt->DontExpand() ? nCmp == *pEnd-1 162 : nCmp == *pEnd ) )) 163 { 164 rShell.CallChgLnk(); 165 return; 166 } 167 nStart = 0; 168 } 169 } 170 171 if( pBreakIt->GetBreakIter().is() ) 172 { 173 const String& rTxt = ((SwTxtNode*)pCNd)->GetTxt(); 174 if( !nCmp || 175 pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp ) 176 != pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp - 1 )) 177 { 178 rShell.CallChgLnk(); 179 return; 180 } 181 } 182 } 183 else 184 /* wenn mit Home/End/.. mehr als 1 Zeichen getravellt, dann 185 * immer den ChgLnk rufen, denn es kann hier nicht 186 * festgestellt werden, was sich geaendert; etwas kann 187 * veraendert sein. 188 */ 189 rShell.CallChgLnk(); 190 } 191 192 const SwFrm* pFrm; 193 const SwFlyFrm *pFlyFrm; 194 if( !rShell.ActionPend() && 0 != ( pFrm = pCNd->getLayoutFrm(rShell.GetLayout(),0,0,sal_False) ) && 195 0 != ( pFlyFrm = pFrm->FindFlyFrm() ) && !rShell.IsTableMode() ) 196 { 197 const SwNodeIndex* pIndex = pFlyFrm->GetFmt()->GetCntnt().GetCntntIdx(); 198 ASSERT( pIndex, "Fly ohne Cntnt" ); 199 200 if (!pIndex) 201 return; 202 203 const SwNode& rStNd = pIndex->GetNode(); 204 205 if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode || 206 nNode > rStNd.EndOfSectionIndex() ) 207 rShell.GetFlyMacroLnk().Call( (void*)pFlyFrm->GetFmt() ); 208 } 209 } 210 211 long SwCallLink::getLayoutFrm( const SwRootFrm* pRoot, SwTxtNode& rNd, xub_StrLen nCntPos, sal_Bool bCalcFrm ) 212 { 213 SwTxtFrm* pFrm = (SwTxtFrm*)rNd.getLayoutFrm(pRoot,0,0,bCalcFrm), *pNext = pFrm; 214 if ( pFrm && !pFrm->IsHiddenNow() ) 215 { 216 if( pFrm->HasFollow() ) 217 while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() ) && 218 nCntPos >= pNext->GetOfst() ) 219 pFrm = pNext; 220 221 return pFrm->Frm().Left(); 222 } 223 return 0; 224 } 225 226