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